如何在 Perl 中的套接字上设置“SO_RCVTIMEO”?
如果我这样尝试:
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 机器上)
If I try like this:
my $sock = IO::Socket::INET->new( … ) or die "no socket for you";
defined $sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, 30) or die "setsockopt: $!";
then my script suffers death from "setsockopt: Invalid argument at [line 2]". The IO::Socket
and perlfunc
pods do not say, though perlfunc gives an example with TCP_NODELAY
which makes it look like the above should work.
(quick note: I've answered my own question, as best I can, but certainly welcome a better answer. The most obvious "better" would be for it to be portable, at least on POSIX machines)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过在运行脚本的 Perl 解释器上使用
strace
,很明显问题在于 Perl 没有打包struct timeval
(SO_RCVTIMEO) 为您服务。此外,似乎没有辅助函数可以为您完成此操作。相反,你必须自己做。
事实证明这是有问题的,因为 struct timeval 是特定于机器的。 Single Unix 规范定义了它:
它还表示
time_t
是整数或实浮点类型,并且“suseconds_t
应是有符号整数类型,能够将值存储在至少在 [-1, 1000000] 范围内”(参见 sys/types.h)。如果无法访问 C 结构,就不可能可移植地执行此操作。但如果我们假设 glibc,它有一个更严格的定义,将两者都指定为
long
,并且它们是唯一的两个成员。但是,这是一个文档错误。所以没关系。因此,我能做的最好的事情是:
pack
格式l!
的意思是:使用当前机器的本机long
——这是 glibc 文档所说的,并且显然至少是为某些 glibc 架构实现的(但根据 bug,不是 SPARC)。By using
strace
on the Perl interpreter running the script, it becomes clear that the problem is that Perl isn't packing astruct timeval
(required bySO_RCVTIMEO
) for you. Further, there do not appear to be helper functions to do it for you. Instead, you must do it yourself.This turns out to be problematic because
struct timeval
is machine-specific. The Single Unix Specification defines it:It also says that
time_t
is an integer or real-floating type, and "suseconds_t
shall be a signed integer type capable of storing values at least in the range [-1, 1000000]" (see sys/types.h).Without access to the C structure, it isn't possible to do this portably. But if we assume glibc, that has a more restrictive definition, specifying both as
long
, and that they're the only two members. However, this is a documentation bug. So never mind.So, the best I can do, which I believe works on both GNU/Linux IA-32 and GNU/Linux AMD64, is this:
The
pack
formatl!
means to use the current machine's nativelong
—which is what the glibc docs say, and is apparently implemented for at least some glibc architectures (but not SPARC, according to the bug).$myiosockinet->timeout( 30 );
或$myiosockinet->timeout( 30 * 1000000 );
有效吗?如果没有,则该模块(
IO::Socket::INET
或Socket
)需要更新 :) 因为 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 不令人满意Does
$myiosockinet->timeout( 30 );
or$myiosockinet->timeout( 30 * 1000000 );
work?If it doesn't, that module (
IO::Socket::INET
orSocket
) needs an update :) because 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 is unsatisfying