[Perl] Timeout sur socket

Timeout sur socket [Perl] - Perl - Programmation

Marsh Posté le 01-07-2005 à 17:34:15    

J'ai une petite application client/serveur
 
le serveur tourne en permanence
 
j'aimerais éviter qu'un petit malin s'amuse à bloquer le tout en effectuant un telnet sur le port et en n'envoyant aucune chaine.
 
Je ne peux pas mettre qu'un simplement timeout sur le socket parce que certaine commande que le client demande peuvent prendre beaucoup de temps
 
ce que je cherche, c'est plutot un timeout sur un "non-envoi" de commande par le client.
 
voici une utilisation normale
 
C se connecte à S
C envoit une commande à S
S effectue la commande
S envoit la réponse à C
C se déconnecte
 
je veux éviter
 
C se connecte à S
C glande pendant des heures et bloque le socket
 
une idée?

Reply

Marsh Posté le 01-07-2005 à 17:34:15   

Reply

Marsh Posté le 04-07-2005 à 10:06:17    

si tu est sous windows tu n'as pas le choix: il faut que tu fasse un select.
Si tu est sous linux tu peux aussi utiliser alarm. par contre apres ca va dependre de la version de perl que tu utilise (safe signals ou pas....) et du coup il vaudra mieux utiliser les signaux posix. Le mieux c'est d'utiliser ce module: Sys::SigAction. il va gerer les conneries de safe/ unsafe et tout de bordel.
 
Mais dans tous els cas la solution du select est sand doute plus propre:
tu fais ton socket et tu attends qu'il ai kkchose à lire avec un select (ou IO::Select si t'es pas à cheval sur les perfs).
Par contre si tu veux lire une ligne (ou utiliser read au lieu de sysread) tu risque à nouveau de bloquer si il n'y a pas assez de choses à lire. dans ce cas il faut passer aux sockets non bloquants... (et la encore c'est different sous windows et unix!)
 
tiens voila des functions qui devraient marcher pour ca:

Code :
  1. use POSIX ();
  2. use constant WIN32 => $^O =~ /win32/i;
  3. use constant O_NONBLOCK  => &POSIX::O_NONBLOCK;
  4. use constant F_GETFL  => &POSIX::F_GETFL;
  5. use constant F_SETFL  => &POSIX::F_SETFL;
  6. sub nonblock {
  7. my $sock = shift;
  8. if (WIN32) {
  9.  my $set_it = "1";
  10.  ioctl( $sock, 0x80000000 | (4 << 16) | (ord('f') << 8) | 126, $set_it) || return 0;
  11. } else {
  12.  fcntl($sock, F_SETFL, fcntl($sock, F_GETFL, 0) | O_NONBLOCK) || return 0;
  13. }
  14. }
  15. sub block {
  16. my $sock = shift;
  17. if (WIN32) {
  18.  my $set_it = "0";
  19.  ioctl( $sock, 0x80000000 | (4 << 16) | (ord('f') << 8) | 126, $set_it) || return 0;
  20. } else {
  21.  fcntl($sock, F_SETFL, fcntl($sock, F_GETFL, 0) & ~O_NONBLOCK) || return 0;
  22. }
  23. }


 
(j'importe les constantes à la main pasqu'en fait, commme pour bcp de modules basées sur des .h, ce ne sont pas de vraies constantes mais des appels de fonction => en faisant un use constant on est certain d'avoir de vraies belles constantes compilées)

Reply

Marsh Posté le 04-07-2005 à 12:56:06    

c'est sous AIX, perl-5.8.3

Reply

Marsh Posté le 04-07-2005 à 13:41:15    

hum jvois pas trop comment intégré tout ca
 
je lance une alarme qui après X seconde va débloquer mon socket
 
si je recois de l'input du socket, j'annule l'alarme
 
c'est un peu ca?

Reply

Marsh Posté le 04-07-2005 à 13:53:26    

en gros (avec la fonction alarm de perl, mais le mieux est d'utiliser Sys::SigAction), tu fais comme ca:
 
local $SIG{ALRM} = {die "timeout"};
eval{
   alarm 10;
   read...
   alarm 0; # pour annuller l'alarme
}
alarm 0;
if ($@) {
   if ($@ eq 'timeout') {
 ....
 
   }
}

Reply

Marsh Posté le 04-07-2005 à 13:55:00    

hum...
 
local $SIG{ALRM} = {die "timeout"};  
 
ton die "timeout" se fera du coté serveur right?
donc ca arretera le daemon qui ne doit pas s'arreter?

Reply

Marsh Posté le 04-07-2005 à 13:55:07    

mais bon dans tous els cas si tu veux un truc plus fin, il va falloir gerer tout ca de maniere asynchrone ou multi tache (POE, Net::Server, IO::multiplex et autres modules du genre...)

Reply

Marsh Posté le 04-07-2005 à 13:55:32    

non car il y a un eval

Reply

Marsh Posté le 04-07-2005 à 13:59:45    

dac je test ca jeudi au boulot et je t'en redonne des nouvelles
 
 
merci

Reply

Marsh Posté le 09-07-2005 à 18:03:49    

ca fonctionne #1
 
merci

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed