Passa al contenuto principale

Il seguente frammento di codice STCP dimostra un problema che ho osservato. Si blocca sulla chiamata recv fino a quando non ci sono dati da leggere, poi elabora i dati ricevuti e chiama di nuovo recv che ritornerà con più dati (o un errore) o si blocca. Se si è verificato un errore, recv restituirà un -1 e il codice di errore è impostato nella variabile errno. Il codice vi sembra corretto?

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

Il codice presuppone che il peer remoto non chiuderà mai con grazia la connessione. Quando il peer remoto fa una chiusura aggraziata, cioè chiama la funzione di chiusura o di spegnimento, recv lo indica all'applicazione locale restituendo zero byte. Le successive chiamate a recv continueranno a restituire zero byte. Il risultato è che il codice è ora in un loop stretto senza fare nulla. Per esempio

numero di byte ricevuti : 8
numero di byte ricevuti : 57
numero di byte ricevuti : 16
numero di byte ricevuti : 1
numero di byte ricevuti : 1
numero di byte ricevuti : 0
numero di byte ricevuti : 0
numero di byte ricevuti : 0
numero di byte ricevuti : 0
numero di byte ricevuti : 0
. . . . .

Anche se il protocollo dell'applicazione prevede che il peer remoto non chiuderà mai con grazia la connessione, non si può garantire che la connessione non sarà mai chiusa con grazia. L'applicazione remota può avere un bug o lo stack TCP remoto può fare una chiusura aggraziata quando il processo applicativo termina. O forse qualche altra applicazione ha fatto una connessione e poi l'ha chiusa quando non ha ottenuto la risposta che si aspettava. Anche un controllo di sicurezza (o un utente malintenzionato) che fa una scansione delle porte o un banner grazioso può fare una chiusura aggraziata. La linea di fondo è che bisogna sempre gestire il caso di zero byte.

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

numero di byte ricevuti : 28
numero di byte ricevuti : 2
numero di byte ricevuti : 58
ricevuto vicino

 

© 2024 Stratus Technologies.