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

标签 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: $!";

然后我的脚本死于“setsockopt:[第 2 行] 处的参数无效”。 IO::Socketperlfunc 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/

相关文章:

perl - 将哈希分配给哈希

perl - 使用 perl 的 reduce 计算点积

java - 什么是 TCP 窗口更新?

linux - 如何在 MacOS/Ubuntu 中重新绑定(bind)套接字?第二次

c - 本地套接字选项集与指向套接字选项集的指针

c - Linux 原始套接字缓冲区大小是否有 256 K 的上限?

Perl+PostgreSQL : a function does not return a value if RAISE NOTICE is present

python - 使用 perl 或 python 更改文本

java - Thrift 客户端/服务器在空闲期后响应时间不稳定

python - Python 和 C 之间 ntohl 和 htonl 的不同行为