如何在 Perl 的套接字上设置`SO_RCVTIMEO`? [英] How do I set `SO_RCVTIMEO` on a socket in Perl?

查看:64
本文介绍了如何在 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::Socketperlfunc pod 没有说,尽管 perlfunc 给出了一个带有 TCP_NODELAY 的例子,这使它看起来像上面应该工作.

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.

(快速说明:我已经尽我所能回答了我自己的问题,但当然欢迎一个更好的答案.最明显的更好"是它至少是便携的在 POSIX 机器上)

(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)

推荐答案

通过在运行脚本的 Perl 解释器上使用 strace,很明显问题在于 Perl 没有打包 stracecode>struct timeval(SO_RCVTIMEO 需要)为您服务.此外,似乎没有辅助功能可以为您完成此操作.相反,你必须自己做.

By using strace on the Perl interpreter running the script, it becomes clear that the problem is that Perl isn't packing a struct timeval (required by SO_RCVTIMEO) for you. Further, there do not appear to be helper functions to do it for you. Instead, you must do it yourself.

事实证明这是有问题的,因为 struct timeval 是特定于机器的.单一 Unix 规范定义它:

This turns out to be problematic because struct timeval is machine-specific. The Single Unix Specification defines it:

标题应定义 timeval 结构,其中至少应包括以下成员:

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).

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).

如果不访问 C 结构,就不可能以可移植的方式执行此操作.但是如果我们假设 glibc 有一个更严格的定义,将两者都指定为 long,并且它们是仅有的两个成员.但是,这是一个文档错误.所以没关系.

Without access to the C structure, it this 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.

所以,我认为它适用于 GNU/Linux IA-32 和 GNU/Linux AMD64 的最佳方法是:

So, the best I can do, which I believe works on both GNU/Linux IA-32 and GNU/Linux AMD64, is this:

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

pack 格式 l! 表示使用当前机器的本地 long——这是 glibc 文档所说的,并且显然是实现的至少对于一些 glibc 架构(但不是 SPARC,根据错误).

The pack format l! means to use the current machine's native long—which is what the glibc docs say, and is apparently implemented for at least some glibc architectures (but not SPARC, according to the bug).

这篇关于如何在 Perl 的套接字上设置`SO_RCVTIMEO`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆