【问题标题】:recv blocking on Perl even though socket is non blocking即使套接字是非阻塞的,Perl 上的 recv 也会阻塞
【发布时间】:2012-08-10 04:48:05
【问题描述】:

我在 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 调用变为非阻塞。

我用谷歌搜索过,但看不到使用 UDP 非阻塞套接字的建议方法。

【问题讨论】:

  • 我已经从标题中删除了“not”,因为我认为这就是你想要的(原来的方式没有意义)
  • 你能尝试在strace 下运行一个测试用例来捕捉它吗?您看到它与接口更改相关的事实意味着这可能是一个内核错误。

标签: perl sockets


【解决方案1】:

首先,字面上的答案:

# 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

【讨论】:

  • 非常感谢您的回答,太好了!一方面,您为我需要快速编码的内容提供了一个快速的功能解决方案。另一方面,你也给了我一个很好的学习模块,从长远来看,这将改变我所做的事情。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 2011-09-13
  • 1970-01-01
  • 2023-03-19
  • 2010-10-31
  • 2013-10-15
  • 1970-01-01
相关资源
最近更新 更多