Pular para o conteúdo principal

O seguinte fragmento de código STCP demonstra um problema que tenho observado. Ele bloqueia na chamada de recv até que haja dados a serem lidos, depois processa os dados recebidos e chama novamente o recv que retornará com mais dados (ou um erro) ou bloqueio. Se ocorrer um erro, o recv retornará um -1 e o código de erro será definido na variável errno. O código parece OK para você?

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

O código pressupõe que o ponto remoto nunca fechará graciosamente a conexão. Quando o ponto remoto faz um fechamento gracioso, ou seja, chama a função de fechamento ou desligamento, o recv indica isso para a aplicação local, retornando zero bytes. As chamadas subseqüentes ao recv continuarão a retornar zero bytes. O resultado é que o código agora está em um loop apertado, sem fazer nada. Por exemplo

número de bytes recebidos : 8
número de bytes recebidos : 57
número de bytes recebidos : 16
número de bytes recebidos : 1
número de bytes recebidos : 1
número de bytes recebidos : 0
número de bytes recebidos : 0
número de bytes recebidos : 0
número de bytes recebidos : 0
número de bytes recebidos : 0
. . . . .

Mesmo que o protocolo de aplicação dite que o ponto remoto nunca fechará graciosamente a conexão, você não pode garantir que a conexão nunca será fechada graciosamente. A aplicação remota pode ter um bug ou a pilha TCP remota pode fazer um fechamento gracioso quando o processo de aplicação terminar. Ou talvez alguma outra aplicação fez uma conexão e depois a fechou quando não obteve a resposta esperada. Uma auditoria de segurança (ou um usuário malicioso) fazendo uma varredura de porta ou um agarramento de banner também pode fazer um fechamento gracioso. O resultado final é que você sempre tem que lidar com o caso de zero bytes.

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

número de bytes recebidos : 28
número de bytes recebidos : 2
número de bytes recebidos : 58
recebido perto

 

© 2024 Stratus Technologies.