Errores de socket irregulares (10054) en la aplicación de Windows

Estoy trabajando en una aplicación de Windows (Microsoft Visual C++ 2005) que usa varios procesos que se ejecutan en diferentes hosts en una intranet.

Los procesos se comunican entre sí mediante TCP/IP. Diferentes procesos pueden estar en el mismo host o en diferentes hosts (es decir, la comunicación puede ser tanto dentro del mismo host como entre diferentes hosts).

Actualmente tenemos un error que aparece de forma irregular. La comunicación parece funcionar por un tiempo, luego deja de funcionar. Luego vuelve a funcionar durante algún tiempo.

Cuando la comunicación no funciona, obtenemos un error (aparentemente mientras un proceso intentaba enviar datos). La llamada se ve así:

send(socket, (char *) data, (int) data_size, 0);

Al inspeccionar el código de error que obtenemos de

WSAGetLastError()

vemos que es un error 10054. Esto es lo que encontré en la documentación de Microsoft (ver aquí):

WSAECONNRESET
10054

Connection reset by peer.

An existing connection was forcibly closed by the remote host. This normally
results if the peer application on the remote host is suddenly stopped, the
host is rebooted, the host or remote network interface is disabled, or the
remote host uses a hard close (see setsockopt for more information on the
SO_LINGER option on the remote socket). This error may also result if a
connection was broken due to keep-alive activity detecting a failure while
one or more operations are in progress. Operations that were in progress
fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

Entonces, según tengo entendido, la conexión fue interrumpida por el proceso de recepción. En algunos casos, este error es (AFAIK) correcto: un proceso ha finalizado y, por lo tanto, no es accesible. En otros casos, tanto el remitente como el receptor están ejecutando y registrando actividad, pero no pueden comunicarse debido al error anterior (el error se informa en los registros).

Mis preguntas.

  • ¿Qué significa la opción SO_LINGER?
  • ¿Qué es una actividad de mantenimiento y cómo puede romper una conexión?
  • ¿Cómo es posible evitar este problema o recuperarse de él?

Con respecto a la última pregunta. La primera solución que probamos (en realidad, es más bien una solución alternativa) fue volver a enviar el mensaje cuando se produce el error. Desafortunadamente, el mismo error ocurre una y otra vez durante un tiempo (unos minutos). Así que esto no es una solución.

Por el momento no entendemos si tenemos un problema de software o un problema de configuración: ¿quizás deberíamos verificar algo en el registro de Windows?

Una hipótesis era que el sistema operativo se queda sin puertos efímeros (en caso de que se cierren las conexiones pero los puertos no se liberan debido a TcpTimedWaitDelay), pero al analizar este problema creemos que debería haber muchos: el problema ocurre incluso si los mensajes no son enviado con demasiada frecuencia entre procesos. Sin embargo, todavía no estamos 100% seguros de que podamos excluir esto: los puertos efímeros pueden perderse de alguna manera (???)

Otro detalle que podría ayudar es que el envío y la recepción ocurren en cada proceso simultáneamente en subprocesos separados: ¿existen estructuras de datos compartidas en las bibliotecas TCP/IP que podrían corromperse?

Lo que también es muy extraño es que el problema ocurre de manera irregular: la comunicación funciona bien durante unos minutos, luego no funciona durante unos minutos y luego vuelve a funcionar.

Gracias por cualquier idea y sugerencia.

EDITAR

Gracias por las pistas que confirman que la única explicación posible era un error de conexión cerrada. Mediante un análisis más detallado del problema, descubrimos que el proceso del lado del servidor de la conexión se había bloqueado/se había terminado y se había reiniciado. Así que había un nuevo proceso de servidor ejecutándose y escuchando en el puerto correcto, pero el cliente no lo había detectado y todavía estaba intentando usar la conexión anterior. Ahora tenemos un mecanismo para detectar tales situaciones y restablecer la conexión en el lado del cliente.

preguntado el 12 de junio de 12 a las 14:06

Hola, Giargio, tengo el mismo problema en c# para una conexión RDP (3389). Pero la conexión se rompe es de 50 segundos. -

2 Respuestas

Ese error significa que la conexión fue cerrada por el sitio remoto. Así que no puedes hacer nada en tu programa excepto aceptar que la conexión está rota.

Respondido el 12 de junio de 12 a las 14:06

Sí, pero el sitio remoto es otro proceso dentro de nuestra aplicación. El sitio remoto se está ejecutando cuando cierra la conexión. Estamos tratando de entender por qué las conexiones se cierran sin razón aparente. - Giorgio

¿Ha establecido un tiempo de espera de conexión? - requirir

Tenemos SO_SNDTIMEO, SO_RCVTIMEO == 3 segundos. - Giorgio

Acabo de comprobar que también tenemos un tiempo de espera de conexión de 5 segundos. - Giorgio

Ese podría ser el problema. Que se agote el tiempo de conexión. Intente depurar el valor 0. - requirir

Estuve enfrentando este problema durante algunos días recientemente y descubrí que la actualización de Adobe Acrobat Reader era la culpable. Tan pronto como desinstales completamente Adobe del sistema, todo vuelve a la normalidad.

respondido 14 mar '16, 19:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.