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 |