我正在尝试使用无效端口连接到某个主机,我想在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秒后如预期的那样.