java.net.SocketException: Restablecimiento de la conexión

Estoy recibiendo el siguiente error al intentar leer de un socket. Estoy haciendo un readInt() en ese InputStream, y estoy recibiendo este error. Al leer la documentación esto sugiere que la parte del cliente de la conexión cerró la conexión. En este escenario, yo soy el servidor.

Tengo acceso a los archivos de registro del cliente y no está cerrando la conexión, y de hecho sus archivos de registro sugieren que estoy cerrando la conexión. ¿Alguien tiene una idea de por qué ocurre esto? ¿Qué más hay que comprobar? ¿Surge esto cuando hay recursos locales que quizás están alcanzando umbrales?


Sí observo que tengo la siguiente línea:

socket.setSoTimeout(10000);

justo antes de readInt(). Hay una razón para esto (una larga historia), pero sólo por curiosidad, ¿hay circunstancias en las que esto podría conducir al error indicado? Tengo el servidor corriendo en mi IDE, y por casualidad dejé mi IDE atascado en un punto de interrupción, y entonces noté que empezaron a aparecer exactamente los mismos errores en mis propios registros en mi IDE.

En fin, sólo lo mencionaba, espero que no sea una pista falsa. :-(

Hay varias causas posibles.

  1. El otro extremo ha reiniciado deliberadamente la conexión, de una manera que no documentaré aquí. Es raro, y generalmente incorrecto, que el software de aplicación haga esto, pero no es desconocido para el software comercial.

  2. Más comúnmente, es causado por escribir en una conexión que el otro extremo ya ha cerrado normalmente. En otras palabras, un error de protocolo de la aplicación.

  3. También puede ser causado por el cierre de un socket cuando hay datos no leídos en el buffer de recepción del socket.

  4. En Windows, 'el software provocó la interrupción de la conexión', que no es lo mismo que 'el reinicio de la conexión', es causado por problemas de red que se envían desde su extremo. Hay un artículo de la base de conocimientos de Microsoft sobre esto.

Comentarios (1)

El restablecimiento de la conexión significa simplemente que se ha recibido un RST TCP. Esto ocurre cuando tu peer recibe datos que no puede procesar, y puede haber varias razones para ello.

La más simple es cuando cierras el socket, y luego escribes más datos en el flujo de salida. Al cerrar el socket, le has dicho a tu compañero que has terminado de hablar, y que puede olvidarse de tu conexión. Cuando envías más datos en ese flujo de todos modos, el peer lo rechaza con un RST para hacerte saber que no está escuchando.

En otros casos, un cortafuegos intermedio o incluso el propio host remoto puede "olvidarse" de su conexión TCP. Esto puede ocurrir si no envías ningún dato durante mucho tiempo (2 horas es un tiempo de espera común), o porque el peer fue reiniciado y perdió su información sobre las conexiones activas. El envío de datos en una de estas conexiones desaparecidas provocará también un RST.


Actualización en respuesta a información adicional:

Revise su manejo de la excepción SocketTimeoutException. Esta excepción se lanza si se excede el tiempo de espera configurado mientras se bloquea una operación de socket. El estado del socket en sí mismo no cambia cuando se lanza esta excepción, pero si su manejador de la excepción cierra el socket, y luego intenta escribir en él, estará en una condición de reinicio de la conexión. El objetivo de setSoTimeout() es ofrecer una forma limpia de salir de una operación de read() que de otro modo podría bloquearse para siempre, sin hacer cosas sucias como cerrar el socket desde otro hilo.

Comentarios (2)

Siempre que he tenido problemas extraños como este, suelo sentarme con una herramienta como WireShark y mirar los datos en bruto que se pasan de un lado a otro. Puede que te sorprenda dónde se están desconectando las cosas, y sólo te están notificando cuando intentas leer.

Comentarios (0)