【问题标题】:How do I set `SO_RCVTIMEO` on a socket in Perl?如何在 Perl 的套接字上设置“SO_RCVTIMEO”?
【发布时间】:2012-01-07 05:27:27
【问题描述】:

如果我这样尝试:

my $sock = IO::Socket::INET->new( … )                    or die "no socket for you";
defined $sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, 30)   or die "setsockopt: $!";

然后我的脚本因“setsockopt: Invalid argument at [line 2]”而死亡。 IO::Socketperlfunc pod 没有说,尽管 perlfunc 给出了一个带有 TCP_NODELAY 的示例,这使得上面看起来应该可以工作。

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

【问题讨论】:

    标签: perl sockets setsockopt io-socket


    【解决方案1】:

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

    事实证明这是有问题的,因为struct timeval 是特定于机器的。单一 Unix 规范defines it

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

    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。所以没关系。

    所以,我能做的最好的事情是:

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 不,我试过了(或者至少,我尝试了构造函数中的选项)。从 strace 来看,设置超时似乎是无操作的。如果你看模块代码,它只是设置了一个成员变量,显然只有连接和接受使用。
      猜你喜欢
      • 2014-12-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多