112 votos

Cómo forzar el cierre de un socket en TIME_WAIT?

Puedo ejecutar un programa en linux que a veces se bloquea. Si se abre rápidamente después de eso, se escucha en el zócalo de la 49201 en lugar de 49200 como lo hizo la primera vez. netstat revela que 49200 está en un estado TIME_WAIT.

Hay un programa que se puede ejecutar de inmediato la fuerza de ese socket muda fuera del estado TIME_WAIT?

148voto

Jedi Master Spooky Puntos 2374
/etc/init.d/networking restart

Permítanme elaborar. Protocolo de Control de transmisión (TCP) está diseñado para ser bidireccional, ordenado, confiable y protocolo de transmisión de datos entre dos puntos finales (programas). En este contexto, el término fiable significa que se va a retransmitir los paquetes si se pierde en el medio. TCP garantiza la fiabilidad mediante el envío de Acuse de recibo (ACK) de paquetes para una sola o una serie de paquetes recibidos de los pares.

Esto va de la misma para el control de señales, tales como la terminación de solicitud/respuesta. RFC 793 define el estado de TIEMPO de ESPERA para ser como sigue:

El TIEMPO de ESPERA representa esperando el tiempo suficiente para pasar a ser seguro el TCP remoto recibido el reconocimiento de su conexión solicitud de terminación.

Consulte el siguiente TCP diagrama de estado: alt text

TCP es un protocolo de comunicación bidireccional, por lo que cuando se establece la conexión, no hay una diferencia entre el cliente y el servidor. También, uno puede llamar se cierra, y tanto ellos debe estar de acuerdo en cerrar para cerrar por completo una conexión TCP establecida.

Vamos a llamar a la primera en llamar a el se cierra como el activo más cerca, y el otro punto el pasivo más cerca. Cuando el activo más cerca envía fin, el estado que va a la fin-WAIT-1. A continuación, se recibe un ACK para el envió de la ALETA y el estado que va a la fin-WAIT-2. Una vez que se recibe de la ALETA también desde el pasivo más cerca, el activo más cerca envía el ACK a la ALETA y el estado va a ESPERAR. En caso de que el pasivo más cerca no se ha recibido la CONFIRMACIÓN de la segunda ALETA, se retransmitirá el paquete fin.

RFC 793 establece el TIEMPO de espera para ser el doble de la duración Máxima del Segmento, o 2MSL. Desde MSL, el tiempo máximo que un paquete puede pasear por Internet, es de 2 minutos, 2MSL es de 4 minutos. Ya que no hay CONFIRMACIÓN a un ACK, el activo más cerca no puede hacer nada sino esperar 4 minutos si se adhiere al protocolo TCP/IP correctamente, en caso de que el pasivo de remitente no ha recibido el ACK a su FIN (en teoría).

En realidad, los paquetes que faltan son probablemente muy raro y muy raro y si todo sucede dentro de la LAN o dentro de una sola máquina.

Para responder a la pregunta pie de la letra, Cómo la fuerza a cerrar un socket en TIME_WAIT?, Todavía me va a seguir mi respuesta original:

/etc/init.d/networking restart

Prácticamente hablando, me gustaría que el programa que lo ignora el estado de TIEMPO de ESPERA utilizando la opción SO_REUSEADDR como WMR mencionado. ¿Qué hace exactamente SO_REUSEADDR hacer?

Este socket opción le indica al kernel que incluso si este puerto está ocupado (en
el estado TIME_WAIT), ir por delante y la reutilización de todos modos. Si está ocupado, pero con otro estado, usted todavía va a conseguir una dirección ya está en uso de error. Es es útil si el servidor ha sido cerrada hacia abajo y, a continuación, reinicie de inmediato mientras que tomas son todavía activos en su puerto. Usted debe ser consciente de que si cualquier imprevisto de datos viene en, que puede confundir a su servidor, pero mientras este es posible, no es probable.

51voto

WMR Puntos 701

No sé si tienes el código fuente de ese programa en particular que se está ejecutando, pero si es así, usted podría poner SO_REUSEADDR a través de setsockopt(2) que permite enlazar en la misma dirección local incluso si el socket está en estado TIME_WAIT (a menos que el socket está escuchando activamente, ver socket(7)).

Para obtener más información sobre el estado TIME_WAIT ver el socket de Unix de preguntas frecuentes.

32voto

Ben Hamill Puntos 655

Que yo sepa no hay ninguna manera de forzar cierre el socket fuera de la escritura una mejor manejador de señal en su programa, pero hay una de ficheros /proc que controla el tiempo que el tiempo de espera de la toma. El archivo es

/proc/sys/net/ipv4/tcp_tw_recycle

y se puede configurar el tiempo de espera de 1 segundo por hacer esto:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

Sin embargo, esta página contiene una advertencia sobre los posibles problemas de confiabilidad cuando el ajuste de esta variable.

También hay un archivo relacionado

/proc/sys/net/ipv4/tcp_tw_reuse

controla si TIME_WAIT sockets pueden ser reutilizados (presumiblemente sin ningún tiempo de espera).

Por cierto, la documentación del kernel advierte que de no cambiar cualquiera de estos valores, sin los consejos de los/las solicitudes de expertos técnicos'. Que yo no soy.

El programa debe de haber sido escrito para intentar una unión a puerto 49200 y luego se incrementa en 1 si el puerto ya está en uso. Por lo tanto, si usted tiene el control del código fuente, puede cambiar este comportamiento para que espere unos segundos e intente de nuevo en el mismo puerto, en lugar de incrementar.

18voto

akostadinov Puntos 380

En realidad, hay una manera de matar a una conexión killcx. Dicen que funciona en cualquier estado de la conexión (que no he comprobado). Usted necesita saber la interfaz donde la comunicación sucede, sin embargo, parece asumir eth0 por defecto.

ACTUALIZACIÓN: otra solución es el cortador que viene en algunas distribuciones de linux de los repositorios.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: