即使socket无阻塞,也可以在Perl上进行recv阻塞

时间:2012-08-10 04:48:06

标签: perl sockets

我在守护进程中的perl中创建了一个这样的套接字

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

在Linux机器上

在recv调用期间,套接字的行为类似于非阻塞套接字,如预期的那样 $sock->recv($message, 128);

但是,我一直在观察当守护程序运行并接收数据时重新配置eth0上的VIF时,recv调用开始阻塞。

这是一个非常令人困惑的问题。我做了$sock->recv($message, 128, MSG_DONTWAIT);并且recv调用变得非阻塞。

我已经使用Google搜索,但无法看到使用UDP非阻塞套接字的建议方法。

1 个答案:

答案 0 :(得分: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