IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

Comment détecter certaines déconnections de sockets


Sujet :

Linux

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Comment détecter certaines déconnections de sockets
    Bonjour à tous,

    J'ai développé sur un système linux embarqué un serveur multiclient. J'utilise des polls pour gérer l'ensemble des sockets, cependant j'ai un soucis vis à vis de certaines déconnections.

    Je connecte des clients (sous linux ou windows) à mon système via un switch, j'ai fait de petites applis sur chaque client qui se connecte et envoie des données.

    Lorsque je coupe brutalement mes applis sur les clients via un contrôle C (ou fermeture de l'appli), j'arrive à voir sur le serveur la déconnection. Par contre si je débranche le câble réseau qui relie un client au switch, le serveur ne le détecte pas.

    Pour l'ensemble des sockets je les gère avec des polls, pour lesquels je regarde les évènements suivants: POLLIN | POLLHUP | POLLNVAL | POLLERR

    Y'a t-il un moyen de détecter ce genre de déconnection de socket bourrine?

    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par timekill Voir le message
    Lorsque je coupe brutalement mes applis sur les clients via un contrôle C (ou fermeture de l'appli), j'arrive à voir sur le serveur la déconnection. Par contre si je débranche le câble réseau qui relie un client au switch, le serveur ne le détecte pas.
    Et si tu fais un kill -9 de tes clients, tu le vois aussi ??? A mon avis non et c'est le même problème => la socket n'est pas mise au courant que la liaison est coupée...

    Citation Envoyé par timekill Voir le message
    Pour l'ensemble des sockets je les gère avec des polls, pour lesquels je regarde les évènements suivants: POLLIN | POLLHUP | POLLNVAL | POLLERR

    Y'a t-il un moyen de détecter ce genre de déconnection de socket bourrine?
    Hum... ptet si tu écris dedans et que tu vérifies avec ce que renvoie read() si le nb d'octets est correct...

  3. #3
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    la gestion totale de toute erreur est relativement complexe, mais le principe est simple :

    C'est une combinaison de signal et des polls et ioctl, dans un ordre judicieux..


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      /* --- If interrupt provoked by temination of either ends, exits ---*/
       if ( (sig == SIGKILL) || (sig == SIGTERM) || (sig == SIGQUIT)  || 
            (sig == SIGPIPE) || (sig == SIGSTOP) || (NumServer == -9999) )
         {
           if ( DEBUG )
    	 fprintf(stderr,"ONE TERMINATION SIGNAL WAS RECEIVED \n");
     
           End_Of_Session(2);
         }


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
     
    /*
     * C h e c k s _ C o m m u n i c a t i o n
     *
     */
    static int Checks_Communication ( int NumServer )
    {
       int             s, ncar_a_lire, ss ;
       struct pollfd   fds[2] ;
     
       fds[0].events = POLLOUT ;
       fds[1].events = POLLIN ;
     
    /*
    --- Assigns the values for the server to be checked
    */
       if ( NumServer < 0 )
         {
           fds[0].fd = MyServer.Canal_Out ;
           fds[1].fd = MyServer.Canal_In ;
         }
       else
         {
           fds[0].fd = MyServer.Servers[NumServer].Canal_Out ;
           fds[1].fd = MyServer.Servers[NumServer].Canal_In ;
         }
     
       if ( PARTIAL_DEBUG )
         fprintf (stderr, " Checks comm");
     
    /*
    --- Checks the state of the connection
    */
       s = poll (fds, 2, 200 );
       if ( PARTIAL_DEBUG )
         fprintf(stderr,"SORTIE DE POLL = %d\n",s);
     
    /*
    --- Either if failed (busy, frozen, error, or client hangup)
    */
       if ( (s <= 0) || 
    	(fds[0].revents & POLLERR) || (fds[1].revents & POLLERR) )
         {
           if ( s <= 0 )
    	 s = INFO ;
           else
    	 s = WARNING ;
         }
       else
           if ( (fds[1].revents & POLLHUP)|| (fds[0].revents & POLLHUP) ||
                (fds[1].revents & POLLNVAL)|| (fds[0].revents & POLLNVAL) )
    	   s = ERROR ;
           else 
    	 {
    	   /* Otherwise it is ok to try and write on it */
     
    	   ss = ioctl(fds[1].fd, FIONREAD, &ncar_a_lire);
    	   if ( (ncar_a_lire == 0) && (ss >= 0) && (s == 2) && (fds[1].revents & POLLIN) )
    	       s = ERROR ;
    	   else
    	       s = SUCCESS ;
    	 }
     
       if ( PARTIAL_DEBUG )
         fprintf (stderr, " comm ends s= %d on server %d",s,NumServer);
     
       return (s);
    }
    plus quelques subitilités...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
     
     
    /*
     * C h e c k s _ O r i g i n _ O f _ S i g n a l
     *
     */
    static int Checks_Origin_Of_Signal ( void )
    {
       int             s=-2, ss, i, n = 0 , ncar_a_lire=0 ;
     
     
       if ( PARTIAL_DEBUG )
         fprintf (stderr, "Checks Origin");
     
    /*
    --- If it is the main server
    */
       if ( Checks_Communication(-1) == SUCCESS )
         {
           /* Checks the state of the communication */
     
           if ( PARTIAL_DEBUG )
    	 fprintf (stderr, " checks if data on client-server");
     
           ss = ioctl(MyServer.Canal_In,FIONREAD,&ncar_a_lire);
     
           if ( PARTIAL_DEBUG )
    	 fprintf(stderr,"\nSORTIE DE IOCTL ss = %d ncar_a_lire = %d\n",ss, ncar_a_lire);
     
           if ( PARTIAL_DEBUG )
    	 fprintf (stderr, " after checking s %d ncar %d ",ss,ncar_a_lire);
     
           if ( (ss == -1) || (ncar_a_lire != 0) /*|| (ss > 0)*/ )
    	 return (-1) ;
        }
       else
         {
           if ( PARTIAL_DEBUG )
    	 fprintf(stderr,"ERREUR DANS CHECK_COMMUNICATION\n");
     
           return (-9999);
         }
     
    /*
    --- Otherwise, if it is a slave server (we use the return to give for which server it arrived)
    */
       if ( MyServer.NServers > 0 )
         {
           for ( i = 0 ; i < MyServer.NServers ; i++ )
    	 {
    	   if ( (! MyServer.Servers[i].Connected) && 
    		(Optimize_Process) &&
    		(MyServer.Servers[i].DispatchDisconnected) )
    	     continue ;
     
    	   if ( MyServer.Servers[i].Canal_In == 0 )
    	     {
    	       n = n + 1 ;
    	       continue ;
    	     }
     
    	   /* Checks the state of the communication */
    	   if ( Checks_Communication(i) != SUCCESS )
    	     {
    	       s = -10 - i ;
    	       break ;
    	     }
    	   else
    	     {
    	       if ( PARTIAL_DEBUG )
    		 fprintf ( stderr, " checks if data on server %d",i);
     
    	       ncar_a_lire = 0 ;
    	       ss = ioctl(MyServer.Servers[i].Canal_In,FIONREAD,&ncar_a_lire);
     
    	       if ( PARTIAL_DEBUG )
    		 fprintf ( stderr, " After checking s %d ncar %d",ss,ncar_a_lire);
     
    	       if ( (ss == -1) || (ncar_a_lire != 0) )
    		 {
    		   if ( ss == -1 )
    		       s = -10 - i ;
    		   else
    		       s = i ;
     
    		   break ;
    		 }
    	     } 
    	 }
     
           if ( n == MyServer.NServers )
    	 s = -1 ;
         }
     
       if ( PARTIAL_DEBUG )
         fprintf (stderr, " Origin ends");
     
     
       return (s);
    }

    Je n'ai pas le temps d'expliciter mais en regardant tu auras pas mal de pointeurs sur la manière de procéder..

  4. #4
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Merci beaucoup pour vos réponses. Je vais essayer de voir tout ça!

    Merci encore.

  5. #5
    Membre à l'essai
    Inscrit en
    Juin 2006
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 21
    Points : 17
    Points
    17
    Par défaut
    Salut

    Moi je me base généralement sur un Poll couplé avec une vérification de ce que retourne un read ou un write.

    Cela me permet de détecter toutes les déconnexions après une tentative de lecture ou d'écriture suivant une déconnexion, fermeture de socket ...

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Voldo Voir le message
    ..Moi je me base généralement sur un Poll couplé avec une vérification de ce que retourne un read ou un write.

    Cela me permet de détecter toutes les déconnexions après une tentative de lecture ou d'écriture suivant une déconnexion, fermeture de socket ...

    Je ne sais pas si c'est parfait mais je n'ai pas de soucis avec cela:
    c'est même pire que pas parfait

    read ou write crash (au vrai sens de "coredump") si le socket est dans un état non cohérent...

  7. #7
    Membre à l'essai
    Inscrit en
    Juin 2006
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 21
    Points : 17
    Points
    17
    Par défaut
    Salut!

    En effet, je me suis trompé dans le code posté, je fais un poll avant chaque tentative de read ou write avec la vérification sur les PollErr et je ne sais plus quel autre type de messages, des que j'ai de nouveau mon code sous les yeux je poste ca

  8. #8
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Voldo Voir le message
    Salut!

    En effet, je me suis trompé dans le code posté, je fais un poll avant chaque tentative de read ou write avec la vérification sur les PollErr et je ne sais plus quel autre type de messages, des que j'ai de nouveau mon code sous les yeux je poste ca
    comme tu peux le voir dans le code posté ci-dessus, ça ne suffit pas...

    Un poll peut marcher, mais il peut y avaoir encore des cas (l'appel à ioctl est là pour ça) où le poll ne détecte pas toutes les conditions..

    Quant à la lecture ou écriture, j'ai donné ci-dessus le code nécessaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          if ( (i = Check_Communication ( num_bd )) == SUCCESS )
            {
                      /* Ecrire ou lire */
            }

Discussions similaires

  1. [Langue Clavier] Comment détecter le changement de la langue ?
    Par Fares BELHAOUAS dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 30/09/2004, 19h26
  2. [Plugin] Comment instantier certaines classes de ANT ?
    Par relivio dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 01/04/2004, 15h45
  3. Comment détecter un changement du réglage de voume sonore ?
    Par mjlub dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 09/01/2004, 17h43
  4. Comment détecter la frappe d'une touche ?
    Par Bubonik software dans le forum C
    Réponses: 17
    Dernier message: 11/12/2003, 21h52
  5. Réponses: 9
    Dernier message: 01/10/2003, 18h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo