4 Stimmen

recv blockiert in Perl, obwohl der Socket nicht blockiert ist

Ich habe einen Socket wie diesen in Perl in einem Daemon erstellt

IO::Socket::INET->new(LocalPort => $port,
                      Proto => 'udp',Blocking => '0') or die "socket: $@"; 

auf einem Linux-Rechner

Der Socket verhält sich während eines recv-Aufrufs erwartungsgemäß wie ein nicht blockierender Socket $sock->recv($message, 128); .

Ich beobachte jedoch immer wieder, dass, wenn die VIFs auf eth0 neu konfiguriert werden, während der Daemon läuft und Daten empfängt, der recv-Aufruf zu blockieren beginnt.

Dies ist ein sehr verwirrendes Thema. Ich habe $sock->recv($message, 128, MSG_DONTWAIT); und der recv-Aufruf wird nicht mehr blockiert.

Ich habe gegoogelt, konnte aber nicht herausfinden, welche Methode für die Verwendung von nicht blockierenden UDP-Sockets vorgeschlagen wird.

4voto

creaktive Punkte 5155

Erstens, die wörtliche Antwort:

# Portable turn-off-blocking code, stolen from POE::Wheel::SocketFactory.
sub _stop_blocking {
    my $socket_handle = shift;

    # Do it the Win32 way.
    if ($^O eq 'MSWin32') {
        my $set_it = "1";
        # 126 is FIONBIO (some docs say 0x7F << 16)
        # (0x5421 on my Linux 2.4.25 ?!)
        ioctl($socket_handle,0x80000000 | (4 << 16) | (ord('f') << 8) | 126,$set_it) or die "can't ioctl(): $!\n";
    }

    # Do it the way everyone else does.
    else {
        my $flags = fcntl($socket_handle, F_GETFL, 0) or die "can't getfl(): $!\n";
        $flags = fcntl($socket_handle, F_SETFL, $flags | O_NONBLOCK) or die "can't setfl(): $!\n";
    }
}

Ich empfehle Ihnen jedoch dringend die Verwendung von AnyEvent::Handle !

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X