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

发布于 2024-12-18 13:57:06 字数 475 浏览 2 评论 0原文

如果我这样尝试:

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 的示例,这使得上面的代码看起来应该可以工作。

快速说明:我已经尽我所能回答了我自己的问题,但当然欢迎更好的答案。最明显的“更好”是它是可移植的,至少在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷月断魂刀 2024-12-25 13:57:06

通过在运行脚本的 Perl 解释器上使用 strace,很明显问题在于 Perl 没有打包 struct timevalSO_RCVTIMEO) 为您服务。此外,似乎没有辅助函数可以为您完成此操作。相反,你必须自己做。

事实证明这是有问题的,因为 struct timeval 是特定于机器的。 Single Unix 规范定义了它

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

time_t tv_sec 秒。
suseconds_t tv_usec 微秒。

它还表示 time_t 是整数或实浮点类型,并且“suseconds_t 应是有符号整数类型,能够将值存储在至少在 [-1, 1000000] 范围内”(参见 sys/types.h)。

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

因此,我能做的最好的事情是:

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

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

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

The <sys/time.h> header shall define the timeval structure, which
shall include at least the following members:

time_t         tv_sec        Seconds.
suseconds_t    tv_usec       Microseconds.

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:

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

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

人心善变 2024-12-25 13:57:06

$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 不令人满意

Does $myiosockinet->timeout( 30 ); or $myiosockinet->timeout( 30 * 1000000 ); work?

If it doesn't, that module (IO::Socket::INET or Socket) 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文