2010-01-29 13 views

Respuesta

10

TCP no funciona así. El sistema operativo no liberará los recursos, es decir, el descriptor de archivo y, por lo tanto, el puerto, hasta que la aplicación cierre explícitamente el socket o muera, incluso si la pila TCP sabe que el otro lado la cerró. No hay devolución de llamada desde el kernel a la aplicación del usuario al recibir el FIN del par. El SO lo reconoce al otro lado pero espera a que la aplicación llame al close() antes de enviar su paquete FIN. Eche un vistazo al TCP state transition diagram - usted está en el pasivo cerca de caja.

Una forma de detectar una situación como esta sin dedicar un hilo a cada socket es usar la familia de funciones select/poll/epoll/kqueue. El zócalo que se cierra pasivamente se señalará como legible y el intento de lectura devolverá el EOF.

Espero que esto ayude.

+0

Enlace de diagrama de transición de estado TCP da un 404 –

6

Ambas partes tienen que leer desde la conexión, para que puedan detectar cuándo se ha cerrado el par. Cuando read devuelva -1, significará que el otro extremo cerró la conexión y esa es su clave para cerrar su final.

+0

Mi código es un código multiproceso y no puedo desperdiciar uno de mis hilos solo por mirar la conexión y encontrar si está cerrada o no. Debo mencionar que tengo miles de estas conexiones, no solo una. – Shayan

+3

Luego tendrá que cambiar a NIO y hacer IO multiplexado. Debe leer desde el socket de una manera u otra si desea detectar un cierre elegante del par. – nos

0

Es probable que desee tener un grupo de conexión.

+0

No. Simplemente cierre la conexión automáticamente. – Shayan

4

Si todavía está leyendo desde su socket, entonces detectará el -1 cuando se cierre.

Si ya no está leyendo desde su socket, adelante y ciérrelo.

Si no es ninguno de estos, probablemente esté esperando un hilo durante un evento. ¡Esta NO es la forma en que desea manejar miles de puertos! Java comenzará a obtener pukey en alrededor de 3000 hilos en Windows, y mucho menos en Linux (no sé por qué).

Asegúrese de estar utilizando NIO. Use un solo hilo para administrar todos sus puertos (grupo de conexiones). Simplemente debería tomar los datos de un hilo, reenviarlos a una cola. En ese momento, creo que tendré un grupo de subprocesos para sacar los datos de las colas y procesarlos porque el procesamiento de los datos de un puerto llevará algo de tiempo.

La conexión de un hilo a cada puerto NO funcionará, y es la razón principal por la que se necesitaba NIO.

Además, tener algún tipo de mensaje de "Cerrar" como parte de su flujo para activar el cierre del puerto puede hacer que las cosas funcionen más rápido, pero igual tendrá que manejar el -1 para cubrir el caso de flujos interrumpidos

+0

Este lado no sabe si está terminado o no.También enviar un mensaje cercano desde el otro lado es demasiado. la mayoría de las veces, para un mensaje, enviamos dos mensajes. – Shayan

+2

No estoy seguro de lo que quiere decir, pero puede simplemente finalizar un mensaje con un carácter especial o bytecode para decirle al oyente que es el último mensaje. Es bastante libre. –

+1

Si envía unos pocos bytes adicionales para indicar que un cierre es demasiado elevado, entonces o tiene requisitos muy especiales o está sufriendo una optimización prematura. – Confusion

3

La solución habitual es hacer saber al otro lado que va a cerrar la conexión antes de cerrarla. Por ejemplo, en el caso del protocolo SMTP, el servidor enviará '221 Bye' antes de que cierre la conexión.

+0

Aunque esta es una buena optimización, no manejará las conexiones caídas y eventualmente acumulará puertos abiertos. Esto no es aceptable en un sistema con miles de puertos abiertos, pero sí reduce la frecuencia de los escaneos "¿Puedo cerrar este puerto?". –

Cuestiones relacionadas