如果我这样尝试:
my $sock = IO::Socket::INET->new( … ) or die "no socket for you";
defined $sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, 30) or die "setsockopt: $!";
然后我的脚本死于“setsockopt:[第 2 行] 处的参数无效”。 IO::Socket
和 perlfunc
pod 没有说明,尽管 perlfunc 给出了一个带有 TCP_NODELAY
的示例,这使得上面的代码看起来应该有效。
(快速说明:我已经尽我所能回答了我自己的问题,但当然欢迎更好的答案。最明显的“更好”是它可移植,至少在 POSIX 机器上)
最佳答案
通过在运行脚本的 Perl 解释器上使用 strace
,很明显问题是 Perl 没有打包 struct timeval
( 需要SO_RCVTIMEO
) 给你。此外,似乎没有辅助功能可以为您完成。相反,您必须自己动手。
事实证明这是有问题的,因为 struct timeval
是特定于机器的。单一 Unix 规范 defines it :
The header shall define the timeval structure, which shall include at least the following members:
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!
意味着使用当前机器的 native long
——这是 glibc 文档所说的,并且显然已实现至少对于一些 glibc 架构(但不是 SPARC,根据错误)。
关于perl - 如何在 Perl 中的套接字上设置 `SO_RCVTIMEO`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8284243/