7
我想连接到一些主机,使用无效的端口,我想在X秒后超时。怎么做 ?Perl:如何在X秒后获取IO :: Socket :: INET超时?
我的代码:
$sock = new IO::Socket::INET(
PeerAddr => $_[0],
PeerPort => $_[1],
Proto => 'tcp',
Timeout => 2
);
我想连接到一些主机,使用无效的端口,我想在X秒后超时。怎么做 ?Perl:如何在X秒后获取IO :: Socket :: INET超时?
我的代码:
$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 [email protected];
if ($sock->connect(pack_sockaddr_in($rport, $raddr))) {
# ${*$sock}{'io_socket_timeout'} = $timeout;
return $sock;
}
return _error($sock, $!, [email protected] || "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;
# }
显然超时的东西被注释掉,这样expleins为什么它被忽略。
我发现一个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',
Proto => 'tcp',
## timeout => ,
);
$sock->autoflush;
print $sock "$qry\015\012";
undef $/; $data = <$sock>; $/ = "\n";
alarm 0;
};
alarm 0; # race condition protection
return "Error: timeout." if ([email protected] && [email protected] =~ /Timed Out/);
return "Error: Eval corrupted: [email protected]" if [email protected];
不是很优雅,但如果它工作...
让我们验证与缓慢的服务器和客户端不耐烦:
# Impatient Client
use IO::Socket::INET;
$sock = new IO::Socket::INET(
PeerAddr => "localhost",
PeerPort => "10007",
Proto => 'tcp',
Timeout => 2,
);
print <$sock>;
close($sock);
# SlowServer
use IO::Socket::INET;
$sock = new IO::Socket::INET(
LocalAddr => "localhost",
LocalPort => "10007",
Proto => 'tcp',
Listen => 1,
Reuse => 1,
);
$newsock = $sock->accept();
sleep 5;
#while (<$newsock>) {
# print $_;
#}
print $newsock "Some Stuff";
close($newsock);
close($sock);
,如果我们运行这个命令:
[email protected]:~/playpen$ perl server.pl&
[1] 9130
[email protected]:~/playpen$ time perl test.pl
Some Stuff[1]+ Done perl server.pl
real 0m5.039s
user 0m0.050s
sys 0m0.030s
所以igno重新设置2秒的超时时间并运行5秒钟。
现在对方不耐烦客户端:
use IO::Socket::INET;
eval {
local $SIG{ALRM} = sub { die 'Timed Out'; };
alarm 2;
$sock = new IO::Socket::INET(
PeerAddr => "localhost",
PeerPort => "10007",
Proto => 'tcp',
Timeout => 2,
);
print <$sock>;
close($sock);
alarm 0;
};
alarm 0; # race condition protection
print "Error: timeout." if ([email protected] && [email protected] =~ /Timed Out/);
print "Error: Eval corrupted: [email protected]" if [email protected];
〜
并运行它:
[email protected]:~/playpen$ perl server.pl&
[1] 9175
[email protected]:~/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秒后如预期超时。
'Timeout'属性不会被忽略,但它被用在'IO :: Socket'的构造函数中,而不是'IO :: Socket :: INET'。尽管如此,这是一个很好的解决方法,Windows需要类似的东西。 – mob 2010-08-25 22:41:08
这是真的,但它的使用被注释掉在IO :: Socket :: INET的配置子部分中。 AFAICS已设置,但从未在:: INET中使用过。 – 2010-08-25 22:48:47
谢谢,这对我有用。但是,为什么这部分在源代码中有所评论? – code2be 2010-08-25 23:23:18