我正在尝试使用无效端口连接到某个主机,我想在X秒后获得超时.怎么做 ?
我的代码:
- $sock = new IO::Socket::INET(
- PeerAddr => $_[0],PeerPort => $_[1],Proto => 'tcp',Timeout => 2
- );
解决方法
如果你检查你会看到的代码(我从我的Ubuntu 10.04复制它):
- my $timeout = ${*$sock}{'io_socket_timeout'};
- # my $before = time() if $timeout;
- undef $@;
- if ($sock->connect(pack_sockaddr_in($rport,$raddr))) {
- # ${*$sock}{'io_socket_timeout'} = $timeout;
- return $sock;
- }
- return _error($sock,$!,$@ || "Timeout")
- unless @raddr;
- # if ($timeout) {
- # my $new_timeout = $timeout - (time() - $before);
- # return _error($sock,# (exists(&Errno::ETIMEDOUT) ? Errno::ETIMEDOUT() : $EINVAL),# "Timeout") if $new_timeout <= 0;
- # ${*$sock}{'io_socket_timeout'} = $new_timeout;
- # }
显然超时的东西被注释掉了,以便明白它被忽略的原因.
我发现了一个post年约会,从2003年开始讨论.一个建议(在底部)是在一个eval块中打开套接字,它被一个报警信号终止:
- eval {
- local $SIG{ALRM} = sub { die 'Timed Out'; };
- alarm 3;
- my $sock = IO::Socket::INET->new(
- PeerAddr => inet_ntoa( gethostbyname($host) ),PeerPort => 'whois',## timeout =>,);
- $sock->autoflush;
- print $sock "$qry\015\012";
- undef $/; $data = <$sock>; $/ = "\n";
- alarm 0;
- };
- alarm 0; # race condition protection
- return "Error: timeout." if ( $@ && $@ =~ /Timed Out/ );
- return "Error: Eval corrupted: $@" if $@;
不是很优雅,但如果它有效……
让我们用慢速服务器和不耐烦的客户端来验证:
- # Impatient Client
- use IO::Socket::INET;
- $sock = new IO::Socket::INET(
- PeerAddr => "localhost",PeerPort => "10007",Timeout => 2,);
- print <$sock>;
- close($sock);
- # SlowServer
- use IO::Socket::INET;
- $sock = new IO::Socket::INET(
- LocalAddr => "localhost",LocalPort => "10007",Listen => 1,Reuse => 1,);
- $newsock = $sock->accept();
- sleep 5;
- #while (<$newsock>) {
- # print $_;
- #}
- print $newsock "Some Stuff";
- close($newsock);
- close($sock);
如果我们运行这个:
- pti@pti-laptop:~/playpen$perl server.pl&
- [1] 9130
- pti@pti-laptop:~/playpen$time perl test.pl
- Some Stuff[1]+ Done perl server.pl
- real 0m5.039s
- user 0m0.050s
- sys 0m0.030s
所以它忽略了2秒超时并运行了整整5秒.
现在另一个不耐烦的客户:
- use IO::Socket::INET;
- eval {
- local $SIG{ALRM} = sub { die 'Timed Out'; };
- alarm 2;
- $sock = new IO::Socket::INET(
- PeerAddr => "localhost",);
- print <$sock>;
- close($sock);
- alarm 0;
- };
- alarm 0; # race condition protection
- print "Error: timeout." if ( $@ && $@ =~ /Timed Out/ );
- print "Error: Eval corrupted: $@" if $@;
〜
并运行它:
- pti@pti-laptop:~/playpen$perl server.pl&
- [1] 9175
- pti@pti-laptop:~/playpen$time perl test2.pl
- Error: timeout.Error: Eval corrupted: Timed Out at test2.pl line 3.
- real 0m2.040s
- user 0m0.020s
- sys 0m0.010s
是的,这个超时2秒后如预期的那样.