El siguiente fragmento de código STCP ilustra un problema que he observado. Se queda bloqueado en la llamada a `recv` hasta que hay datos que leer; a continuación, procesa los datos recibidos y vuelve a llamar a `recv`, lo que o bien devuelve más datos (o un error), o bien se queda bloqueado. Si se ha producido un error, `recv` devuelve -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 da por sentado que el interlocutor remoto nunca cerrará la conexión de forma controlada. Cuando el interlocutor remoto realiza un cierre controlado, es decir, cuando llama a la función close o shutdown, recv lo indica a la aplicación local devolviendo cero bytes. Las llamadas posteriores a recv seguirán devolviendo cero bytes. El resultado es que el código queda atrapado en un bucle 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 . . . . . |
Aunque el protocolo de la aplicación establezca que el interlocutor remoto nunca cerrará la conexión de forma controlada, no se puede garantizar que la conexión nunca se cierre de forma controlada. La aplicación remota puede tener un error, o la pila TCP remota puede realizar un cierre controlado cuando el proceso de la aplicación finalice. O tal vez alguna otra aplicación haya establecido una conexión y luego la haya cerrado al no recibir la respuesta esperada. Una auditoría de seguridad (o un usuario malintencionado) que realice un escaneo de puertos o una captura de banner también puede realizar un cierre ordenado. La conclusión es que siempre hay que gestionar el caso de 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 se ha recibido el comando «close» |
