2010-08-25 6 views

Répondre

17

Si vous vérifiez le code que vous verrez (je l'ai copié de mon 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; 
#  } 

Apparemment, les choses de délai d'attente est mis en commentaire afin que expleins pourquoi est-il ignoré?

J'ai trouvé un post datant de 2003 où cela a été discuté. Une suggestion (en bas) était d'ouvrir la prise dans un bloc eval qui obtient mis fin par un signal d'alarme:

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]; 

Pas très élégant, mais si cela fonctionne ...

Vérifions avec serveur lent et client impatient:

# 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); 

si nous courons ceci:

[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 

il igno res le délai de 2 secondes et court pendant les 5 secondes entières.

Maintenant, l'autre client impatient:

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]; 

~

et l'exécuter:

[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 

Eh oui, ce délais d'attente au bout de 2 secondes comme prévu.

+1

L'attribut 'Timeout' n'est pas ignoré, mais il est utilisé dans le constructeur de' IO :: Socket', pas 'IO :: Socket :: INET'. C'est une bonne solution de contournement, et quelque chose comme ceci est nécessaire pour Windows. – mob

+0

C'est vrai, mais son utilisation est commentée dans le sous-ensemble de configuration de IO :: Socket :: INET. AFAICS est défini, mais jamais utilisé dans :: INET. –

+0

Merci, ça a marché pour moi. Mais, pourquoi cette partie est commentée dans la source? – code2be

Questions connexes