Ir al contenido principal

A veces netstat mostrará un enchufe que parece estar atascado. La aplicación remota ha sido terminada, a veces incluso la aplicación OpenVOS ha sido terminada pero netstat sigue mostrando el socket. Este artículo explicará por qué sucede esto y qué puede hacer al respecto.

Una breve introducción a los estados del PCT

Si buscas en Google "diagrama de estado tcp" encontrarás una gran cantidad de imágenes, algunas apenas legibles y otras bastante legibles. Wikimedia tiene una muy buena codificada por colores (http://commons.wikimedia.org/wiki/File:TCP_state_diagram.png). El TCP RFC (793) (http://www.rfc-editor.org/rfc/rfc793.txt) tiene un diagrama ASCII artístico y por supuesto explica los estados en detalle.

Los enchufes pueden atascarse cuando están esperando que la aplicación local o el host remoto hagan algo. Hay tres estados en los que esto ocurre. En el estado FIN_WAIT_2 el socket está esperando que el host remoto cierre la conexión. En el estado CLOSE_WAIT está esperando que la aplicación local cierre el socket y en el estado ESTABLISHED está esperando que el host remoto abra su ventana de envío, o que la aplicación local envíe algo. Si la pila TCP local ha enviado datos y está esperando que el host remoto reconozca que no puede atascarse, eventualmente se agotará el tiempo de espera, señalará un error a la aplicación local y cerrará el socket.

FIN_WAIT_2 estado

Este es quizás el caso más común de enchufe atascado que se llama en el CAC. La aplicación local ha cerrado el enchufe y puede haber terminado. La razón típica para que los enchufes se queden atascados en este estado es que la aplicación remota se cuelga y no lee su enchufe.

Ajustando el parámetro STCP finwait2 a unos N > 0 se cerrarán los sockets después de haber estado en el FIN_WAIT_2 durante N segundos. A partir de las versiones 14.7.2bg, 14.7.tl1, 15.2.1aa, 15.2.tel.af, 15.3.0bd, 15.3.tel.ag, 16.2.1al, 17.0.0ai, y 17.1 el valor por defecto es 1200, antes de eso el valor por defecto era 0 (así que si quieres que los sockets se cierren tendrás que configurarlo tú mismo). Puede ver el valor actual con la solicitud list_stcp_params analyze_system, puede modificar el valor con la solicitud set_stcp_param analyze_system. Consulte el manual de análisis del sistema OpenVOS (R073), disponible en http://stratadoc.stratus.com, para obtener documentación sobre estas solicitudes.

Estado CLOSE_WAIT

Este es el siguiente estado de enchufe atascado más común. Los enchufes en estado CLOSE_WAIT esperan a que la aplicación local cierre el enchufe. La razón típica para que un enchufe permanezca en este estado es que la aplicación ya no está leyendo el enchufe. La forma más fácil de cerrar el socket es terminar la aplicación local.

Si terminar la aplicación local no es una opción, lo único que puedes hacer es crear un paquete con la bandera RST (reset) puesta. Esto requiere que conozca los números de secuencia usados por el socket (disponible usando la petición dump_onetcb analyze_system) y tener una utilidad en otro host de la subred local que pueda construir y enviar paquetes IP personalizados. Estas utilidades están disponibles para sistemas Windows y Linux.

ESTADO ESTABLECIDO

Dado que la mayoría de las veces netstat muestra los enchufes en el estado ESTABLECIDO ¿cómo puedes saber cuando el enchufe está atascado? Si tienes un informe de que el host remoto se ha caído o la red entre el host local y el remoto ha fallado durante más de 10 minutos y la aplicación local está esperando que el remoto le envíe algo, puedes estar bastante seguro de que el socket está atascado. En este caso el valor de la cola de envío (el número a la izquierda inmediata de la dirección IP local) reportado por netstat será 0. Por otro lado, si el valor de la cola de envío es mayor que 0 y permanece allí puede tener el caso del host remoto anunciando una ventana cero.

En el primer caso, a menos que se encienda Keep-Alive, el enchufe permanecerá en el estado ESTABLECIDO hasta que se termine la aplicación local. Si se enciende keep-alive, después de que el temporizador de keep-alive expire, STCP enviará una sonda de keep-alive. Si la sonda no recibe respuesta, será retransmitida, pero después de unos minutos y varias retransmisiones, la conexión se terminará. Por defecto, la interfaz tiene configurado el modo "keep-alive" pero también por defecto los enchufes no lo tienen. Para establecer keep-alive en un socket la aplicación debe utilizar la llamada de la función setsockopt. Consulte el manual de programación de OpenVOS STREAMS TCP/IP (R420), también disponible en http://stratadoc.stratus.com, para más detalles. El tiempo de mantenimiento en vida por defecto es de 2 horas; esto significa que la primera sonda de mantenimiento en vida se transmite 2 horas después de que se reciba el último segmento TCP desde el host remoto, por lo que debe ser paciente. Para aquellos que no sean tan pacientes, puede ajustar el tiempo de mantenimiento de vida y también el tiempo entre sondas y el número de sondas con la petición set_stcp_parameter dentro de analyze_system. No recomiendo cambiar estos parámetros sin un análisis detallado.

Si el socket no tiene el conjunto de "keep-alive" la única opción simple es terminar la aplicación que posee el socket. Si no es una opción, es posible cerrar el socket enviándole un segmento con la bandera RST puesta...

Para confirmar el segundo caso compruebe el valor de sndws mostrado por la petición dump_onetcb analyze_system. Un valor 0 indica una ventana cerrada. También puede ejecutar packet_monitor para rastrear la conexión y comprobar el valor de la ventana en el encabezado TCP en segmentos del host remoto. Un valor de "n.a." indica 0.

Quiero recalcar que esta puede ser una condición recuperable. Las aplicaciones a veces se retrasan y la pila de TCP cierra la ventana, cuando la aplicación se queda atrapada la pila abre la ventana. Sin embargo, en la mayoría de los casos creo que es seguro asumir que si la aplicación no se ha recuperado después de unos minutos no lo hará. La excepción podría ser algo como una impresora que se ha quedado sin papel. Un enchufe en este estado puede permanecer en este estado incluso si la aplicación VOS que lo creó termina.

Estos sockets pueden ser limpiados configurando tcp_zerowin_abort_interval$ a unos N > 0. Los sockets se limpiarán N segundos después de que se reciba el siguiente segmento TCP con una ventana cero. Las sondas de ventana son enviadas cada 100 segundos para confirmar que la ventana de recepción del host remoto sigue cerrada, así que en el peor de los casos una respuesta será recibida dentro de 100 segundos. El valor por defecto de tcp_zerowin_abort_interval$ es cero y sugiero que permanezca en 0 a menos que usted necesite limpiar un socket. En ese punto sugiero que lo establezca a un valor pequeño, digamos 10 segundos, y una vez que el socket se limpie reajustarlo a 0. Creo que esto reduce el riesgo de limpiar sockets que son recuperables

Para establecer este valor debes usar la petición set_longword en analyze_system, así que recuerda que N estará en hexadecimal. Por ejemplo, para establecerlo en 10 la petición sería
set_longword tcp_zerowin_abort_interval$ a