2009-12-18 13 views
5

Estoy intentando evitar TIME_WAIT en un cliente. Me conecto y luego configuro O_NONBLOCK y SO_REUSEADDR. Llamo a read hasta que devuelve 0. Cuando read devuelve 0, el errno también es 0. Interpreté esto como una señal de que el servidor cerró la conexión. Sin embargo, si llamo close, el socket se establece en TIME_WAIT, como lo confirma netstat.Evitando TIME_WAIT

Dado que realizo varias conexiones al mismo host/puerto, eventualmente empiezo a ver errores de "Dirección en uso" (vea http://hea-www.harvard.edu/~fine/Tech/addrinuse.html).

¿Debo llamar después de que read devuelve 0? Si no, ¿se publicará el descriptor del archivo?

+0

sidenote: errno el valor no está definido cuando se lee devuelve 0 - errno solamente se define después de un fallo. –

Respuesta

5

El lado que es el que inició el cierre de la conexión es el que termina en el estado TIME_WAIT. read() return 0 se supone que indica que el servidor cerró el socket primero, entonces sí - esto debería significar que el TIME_WAIT termina en el lado del servidor, y el cliente pasa por LAST_ACK.

Al final del día, no puede evitar un estado TIME_WAIT. Incluso si logra moverlo del lado del cliente al del servidor, aún no puede volver a utilizar esa tupla (server host, server port, client host, client port) hasta que termine el TIME_WAIT (independientemente de en qué lado esté).

Desde tres partes de esa tupla se fijan en su escenario (server host, server port, client host), que realmente sólo tiene estas opciones:

  • tratar de hacer más puertos de cliente disponible. Algunos sistemas operativos solo usan un pequeño rango de los puertos disponibles para "puertos efímeros" por defecto (no estoy seguro acerca de OSX a este respecto). Si ese es el caso, vea si puede cambiar el rango con un ajuste de configuración en el sistema operativo o, alternativamente, haga que la aplicación busque un puerto en funcionamiento con bind()/connect() en un bucle hasta que la conexión funcione.

  • Expanda el número de valores client host disponibles, mediante el uso de varias direcciones IP en su cliente. Sin embargo, tendrá que tener la aplicación bind() específicamente en una de estas direcciones IP.

  • Expanda el número de valores server host/server port disponibles, mediante el uso de varios puertos y/o direcciones IP en el servidor. El cliente deberá elegir uno para conectarse (round robin, random, etc.).

  • Probablemente la mejor opción, si es factible: refactorizar su protocolo para que las conexiones que se terminen no se cierren, sino que pasen a un estado "inactivo" para que puedan ser reutilizadas más tarde, en lugar de abrir una nueva conexión (como HTTP keep-alive).

+0

Lamento comentar una pregunta anterior, pero ¿no debería el primer párrafo de esta respuesta decir "el lado que INICIÓ el cierre de la conexión es el que termina en el estado TIME_WAIT"? Me parece recordar haber leído eso en algún libro, y también, eso parece estar implícito en http://hea-www.harvard.edu/~fine/Tech/addrinuse.html – zentrunix

+0

@ JoséX .: Sí, tú estas en lo correcto. – caf

1

Más adelante en la misma página mencionan SO_REUSEADDR. Eso es lo que necesitas. Definitivamente desea cerrar el descriptor de archivo de lectura cuando devuelve cero.

+0

Lo siento. Olvidé agregar que YO configuro SO_REUSEADDR. Consulte en el artículo que no evita los errores de Dirección en uso cuando se conecta al mismo puerto/host. – richcollins

0

Configuración SO_REUSEADDR en el lado del cliente no ayuda el lado del servidor a menos que también establece SO_REUSEADDR

Cuestiones relacionadas