Perl:如何在 X 秒后获得 IO::Socket::INET 超时? [英] Perl: How to get IO::Socket::INET timeout after X seconds?

查看:65
本文介绍了Perl:如何在 X 秒后获得 IO::Socket::INET 超时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用无效端口连接到某个主机,并且我想在 X 秒后超时.怎么做?

I'm trying to connect to some host, using invalid port, and i want to get timeout after X seconds. How to do that ?

我的代码:

 $sock = new IO::Socket::INET(
                  PeerAddr => $_[0],
    PeerPort => $_[1],
    Proto => 'tcp',
    Timeout => 2
    );

推荐答案

如果你检查代码你会看到(我从我的 Ubuntu 10.04 复制了它):

If you check the code you'll see (I copied it from my 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;
#        }

显然超时的东西被注释掉了,以便解释为什么它被忽略.

Apparently the timeout stuff is commented out so that expleins why it is ignored.

我发现了一篇 2003 年的帖子,讨论了这个问题.一个建议(在底部)是在 eval 块中打开套接字,该块被警报信号终止:

I found a post dating from 2003 where this was discussed. One suggestion (at the bottom) was to open the socket in an eval block which gets terminated by an alarm signal :

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 $@; 

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

Not very elegant, but if it works...

让我们用缓慢的服务器和不耐烦的客户端来验证:

Let's verify with a slow server and impatient client :

# 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 秒.

So it ignores the 2 second timeout and runs for the full 5 seconds.

现在另一个不耐烦的客户:

Now the other impatient client :

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

Yep, this timeouts after 2 seconds as expected.

这篇关于Perl:如何在 X 秒后获得 IO::Socket::INET 超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆