Skip to main content

Le fragment de code STCP suivant démontre un problème que j'ai observé. Il bloque l'appel recv jusqu'à ce qu'il y ait des données à lire, puis il traite les données reçues et appelle recv à nouveau qui reviendra avec plus de données (ou une erreur) ou bloquera. Si une erreur s'est produite, recv renvoie un -1 et le code d'erreur est défini dans la variable errno. Le code vous semble-t-il correct ?

while (1)
   {
   cBytes = recv (socks1, buffer, BUFFERLEN, 0);
   if (cBytes == -1)
      {
      perror ("Unexpected error at recv");
      exit (errno);
      }
   else
      printf ("number of bytes received : %dn", cBytes);
   }

Le code suppose que le pair distant ne fermera jamais gracieusement la connexion. Lorsque le pair distant effectue une fermeture gracieuse, c'est-à-dire qu'il appelle la fonction de fermeture ou d'arrêt, recv l'indique à l'application locale en renvoyant zéro octet. Les appels ultérieurs à recv continueront à renvoyer zéro octet. Le résultat est que le code est maintenant dans une boucle serrée, sans rien faire. Par exemple

nombre d'octets reçus : 8
nombre d'octets reçus : 57
nombre d'octets reçus : 16
nombre d'octets reçus : 1
nombre d'octets reçus : 1
nombre d'octets reçus : 0
nombre d'octets reçus : 0
nombre d'octets reçus : 0
nombre d'octets reçus : 0
nombre d'octets reçus : 0
. . . . .

Même si le protocole d'application prévoit que le pair distant ne fermera jamais la connexion de manière élégante, vous ne pouvez pas garantir que la connexion ne sera jamais fermée de manière élégante. L'application distante peut avoir un bogue ou la pile TCP distante peut effectuer une fermeture élégante lorsque le processus d'application se termine. Ou peut-être qu'une autre application a établi une connexion et l'a ensuite fermée lorsqu'elle n'a pas obtenu la réponse attendue. Un audit de sécurité (ou un utilisateur malveillant) effectuant un scan de port ou une capture de bannière peut également effectuer une fermeture élégante. En fin de compte, vous devez toujours gérer le cas des octets zéro.

while (1)
   {
   cBytes = recv (socks1, buffer, BUFFERLEN, 0);
   if (cBytes <= 0)
      {
      if (cBytes < 0)
         {
         perror ("Unexpected error at recv");
         exit (errno);
         }
      else
         {
         printf ("received closen");
         close (socks1);
         exit (0);
         }
      }
   else
      printf ("number of bytes received : %dn", cBytes);
   }

nombre d'octets reçus : 28
nombre d'octets reçus : 2
nombre d'octets reçus : 58
reçu de près

 

2024 Stratus Technologies.