2010-11-12 15 views
7

En el cliente, tengo una¿Por qué este servidor que escribo no detecta que el cliente ha cerrado el socket?

close(sockfd) 

donde sockfd es la toma que está conectado al servidor. En el servidor Tengo esto:

if (sockfd.revents & POLLERR || 
    desc_set[i].revents & POLLHUP || desc_set[i].revents & POLLNVAL) { 
    close(sockfd.fd); 
    printf("Goodbye (connection closed)\n"); 
} 

Dónde sockfd es un pollfd estructura y sockfd.fd es el descriptor de archivo de socket del cliente.

Cuando el cliente cierra el socket como lo puse allí, el servidor no parece detectarlo con el segundo código (desc_set [i] .revents & POLLHUP, etc.).

¿Alguien sabe cuál es el problema?

Respuesta

9

Parece que ha logrado half close la conexión desde el lado del cliente. En este estado, la conexión aún puede enviar datos en una dirección, es decir, opera en modo semidúplex. Esto es por diseño y permitiría que su servidor termine de responder a lo que el cliente envió. Normalmente, esto significaría completar una transferencia de archivos y llamar al close(), o responder a todos los aspectos de la consulta. En el estado semicerrado, aún puede enviar datos con bastante sensatez al lado que ya ha llamado al close(). En su servidor, verá eof si intenta leer. close() solo significa "Ya terminé de enviar, termine lo que solicité".

POLLHUP, POLLERR y POLLNVAL solo comprueba el lado de salida de la conexión local, que sigue siendo válida aquí. Hay un POLLRDHUP, que es una extensión de GNU que debería detectar el cierre del otro lado, pero las pruebas que estás haciendo solo comprueban si todavía se puede escribir, no si todavía es legible.

Ver también this question, que está hablando de Java, pero todavía muy relacionado.

+0

Lo siento por hacer una pregunta de novato, pero ¿cómo incluyo esa extensión de GNU en mi código? – dasen

+0

#define _GNU_SOURCE antes de cualquier #includes lo hará. Hacer la llamada al servidor close() de su propio libre albedrío una vez que se sirve la solicitud es mucho, mucho más agradable. – Flexo

+0

He usado esa extensión de GNU, pero todavía no se cierra en el lado del servidor. – dasen

4

Un cierre remoto de cierre o salida no es un error ni un cuelgue ni un estado no válido. Es un evento de lectura tal que read() devolverá cero. Solo tráelo como parte de tu procesamiento de lectura normal.

BTW su condición de prueba anterior debe leer sockfd.revents & (POLLERR | POLLHUP | POLLNVAL).

+0

Derecha: un gracioso 'close()' se indica con 'read()' devolviendo 0, por lo que se indica con 'POLLIN'. – caf

Cuestiones relacionadas