如何在Perl中的套接字上设置`SO_RCVTIMEO`?

时间:2011-11-27 07:28:27

标签: perl sockets setsockopt io-socket

如果我这样做:

my $sock = IO::Socket::INET->new( … )                    or die "no socket for you";
defined $sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, 30)   or die "setsockopt: $!";

然后我的脚本因#34; setsockopt而死亡:[第2行]"中的参数无效。 IO::Socketperlfunc广告连播不说,但是perlfunc给出了TCP_NODELAY的示例,这使得它看起来像上面应该有效。

快速说明:我已经回答了我自己的问题,尽我所能,但肯定会欢迎更好的答案。最明显的"更好"将是它是便携式的,至少在POSIX机器上)

2 个答案:

答案 0 :(得分:3)

通过在运行脚本的Perl解释器上使用strace,很明显问题是Perl没有为您打包struct timevalSO_RCVTIMEO所需)。此外,似乎没有辅助功能为您执行此操作。相反,你必须自己做。

这证明是有问题的,因为struct timeval是特定于机器的。单Unix规范defines it

  

标题应定义时间结构,即   应至少包括以下成员:

time_t         tv_sec        Seconds.
suseconds_t    tv_usec       Microseconds.

它还说time_t是整数或实数浮点类型,“suseconds_t必须是能够存储至少在[-1,1000000]范围内的值的有符号整数类型”(参见sys/types.h

如果不能访问C结构,就不可能这样做。但是如果我们假设glibc,它具有更严格的定义,将两者都指定为long,并且它们是唯一的两个成员。但是,this is a documentation bug。所以没关系。

所以,我认为我能做的最好的事情是GNU / Linux IA-32和GNU / Linux AMD64,它是:

$sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, pack('l!l!', 30, 0))
    or die "setsockopt: $!";

pack格式l!表示使用当前机器的本机long - 这是glibc文档所说的,并且显然是为至少一些glibc架构实现的(但不是SPARC) ,根据bug)。

答案 1 :(得分:0)

$myiosockinet->timeout( 30 );$myiosockinet->timeout( 30 * 1000000 );是否有效?

如果没有,那个模块(IO::Socket::INETSocket)需要更新:)因为http://search.cpan.org/~flora/perl-5.14.2/pod/perlfaq8.pod#Where_do_I_get_the_include_files_to_do_ioctl%28%29_or_syscall%28%29%3F不满意