How do I set `SO_RCVTIMEO` on a socket in Perl?

谁说我不能喝 提交于 2019-12-02 07:15:51

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

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!