Perl: How to get IO :: Socket :: INET timeout after X seconds?

I am trying to connect to some host using an invalid port and I want to get a timeout after X seconds. How to do it?

My code is:

$sock = new IO::Socket::INET( PeerAddr => $_[0], PeerPort => $_[1], Proto => 'tcp', Timeout => 2 ); 
+7
perl networking sockets inet
source share
1 answer

If you check the code you 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 is commented out so that eliminates why it is ignored.

I have found a post since 2003 where it was discussed. One suggestion (below) was to open a socket in the eval block, which ends with an alarm:

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

Check with a slow server and an 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); 

if we run this:

 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 

Thus, it ignores the 2 second timeout and runs for 5 seconds.

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

~

and running it:

 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 

Yes, this is the wait time after 2 seconds, as expected.

+17
source share

All Articles