El siguiente fragmento de código STCP demuestra un problema que he observado. Se bloquea en la llamada recv hasta que hay datos para leer, entonces procesa los datos recibidos y llama de nuevo a recv que volverá con más datos (o un error) o se bloqueará. Si se ha producido un error, recv devolverá un -1 y el código de error se establece en la variable errno. ¿Te parece que el código está bien?
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); } |
El código asume que el par remoto nunca cerrará la conexión con gracia. Cuando el par remoto hace un cierre gracioso, es decir, llama a la función de cierre o apagado, recv lo indica a la aplicación local devolviendo cero bytes. Las llamadas posteriores a recv continuarán devolviendo cero bytes. El resultado es que el código está ahora en un bucle cerrado sin hacer nada. Por ejemplo
número de bytes recibidos: 8 número de bytes recibidos: 57 número de bytes recibidos: 16 número de bytes recibidos : 1 Número de bytes recibidos: 1 Número de bytes recibidos: 0 Número de bytes recibidos: 0 Número de bytes recibidos: 0 Número de bytes recibidos: 0 Número de bytes recibidos: 0 . . . . . |
Incluso si el protocolo de aplicación dicta que el par remoto nunca cerrará la conexión con gracia, no se puede garantizar que la conexión nunca se cierre con gracia. La aplicación remota puede tener un error o la pila TCP remota puede hacer un cierre elegante cuando el proceso de la aplicación termina. O quizás alguna otra aplicación hizo una conexión y luego la cerró cuando no obtuvo la respuesta que esperaba. Una auditoría de seguridad (o un usuario malintencionado) que realice un análisis de puertos o un agarre de banners también puede hacer un cierre elegante. La conclusión es que siempre hay que manejar el caso de los cero 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 recibidos: 28 número de bytes recibidos: 2 número de bytes recibidos: 58 recibió cerca |