gpt4 book ai didi

Perl:如何在 X 秒后获得 IO::Socket::INET 超时?

转载 作者:行者123 更新时间:2023-12-04 09:56:27 24 4
gpt4 key购买 nike

我正在尝试使用无效端口连接到某个主机,并且我想在 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',
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 ( $@ && $@ =~ /Timed Out/ );
return "Error: Eval corrupted: $@" if $@;

不是很优雅,但如果它有效......

让我们用一个缓慢的服务器和不耐烦的客户端来验证:
# 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);

如果我们运行这个:
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",
PeerPort => "10007",
Proto => 'tcp',
Timeout => 2,
);

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 秒后按预期超时。

关于Perl:如何在 X 秒后获得 IO::Socket::INET 超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3570440/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com