Question

Je suis en train de se connecter à un hôte, en utilisant le port non valide, et je veux obtenir délai après X secondes. Comment faire?

Mon code:

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

La solution

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

Apparemment, les choses de délai d'attente est commenté afin que expleins pourquoi il est ignoré.

J'ai trouvé un datant de 2003 après où cela a été discuté. Une suggestion (en bas) était d'ouvrir la douille dans un bloc eval qui obtient terminée 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 ( $@ && $@ =~ /Timed Out/ ); 
return "Error: Eval corrupted: $@" if $@; 

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

Soit de vérifier avec un 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:

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

Il ne tient pas compte du délai de 2 secondes et se poursuit pendant les 5 secondes pleines.

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 ( $@ && $@ =~ /Timed Out/ );
print "Error: Eval corrupted: $@" if $@;

~

et l'exécuter:

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

Oui, ce délais d'attente après 2 secondes comme prévu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top