2012-08-10 125 views
2

我有一臺Linux機器recv的Perl的阻擋,即使插座是不可阻擋

插座的行爲就像非阻塞的插座中能夠按照預期在創造這樣一個插座在Perl的守護

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

如預期的那樣收到一個recv電話 $sock->recv($message, 128);

但是,我始終認爲,當守護進程運行並接收數據時,eth0上的VIF被重新配置時,recv調用開始阻塞。

這是一個非常令人困惑的問題。我做了$sock->recv($message, 128, MSG_DONTWAIT);並且recv呼叫變成了非阻塞。

我已經使用Google,但看不到使用UDP非阻塞套接字的建議方式。

+1

我已經從標題中刪除了「不是」,因爲我認爲這就是你的意圖(它沒有意義的原始方式) – 2012-08-10 04:51:36

+3

你可以嘗試在'strace'下運行一個測試用例來捕獲它嗎?事實上,你看到它與接口的變化相關聯意味着這可能是一個內核錯誤。 – 2012-08-10 05:19:07

回答

2

首先,字面答案:

# 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"; 
    } 
} 

不過,我強烈建議你使用AnyEvent::Handle