無効なポートを使用してホストに接続しようとしていますが、X秒後にタイムアウトを取得したいと思います。どうやってするか ?
私のコード:
$sock = new IO::Socket::INET(
PeerAddr => $_[0],
PeerPort => $_[1],
Proto => 'tcp',
Timeout => 2
);
無効なポートを使用してホストに接続しようとしていますが、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;
# }
どうやらタイムアウトのものはコメントアウトされているので、なぜそれが無視されるのかを説明しています。
私はこれが議論された2003年からの投稿を見つけました。(下部にある)1つの提案は、アラーム信号によって終了する評価ブロックのソケットを開くことでした。
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秒後にタイムアウトします。
IO :: Socket::Timeoutを使用する方がはるかに簡単です
以下のように、それは魅力のように機能します。
use IO::Socket::Timeout;
my $socket = IO::Socket::INET->new( Timeout => 2 );
IO::Socket::Timeout->enable_timeouts_on($socket);
$socket->read_timeout(0.5); # These will work
$socket->write_timeout(0.5); # These will work