java.net.SocketException: restablecimiento de conexión

128

Recibo el siguiente error al intentar leer desde un socket. Estoy haciendo algo readInt()al respecto InputStreamy obtengo este error. Al leer la documentación, esto sugiere que la parte del cliente de la conexión la cerró. 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. Entonces, ¿alguien tiene una idea de por qué sucede esto? ¿Qué más verificar? ¿Esto surge cuando hay recursos locales que tal vez están alcanzando umbrales?


Tengo en cuenta que tengo la siguiente línea:

socket.setSoTimeout(10000);

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

De todos modos, solo mencionándolo, espero que no sea un arenque rojo. :-(

azulado
fuente
¿Tienes rastros de pila de ambos lados? ¿Puedes describir la arquitectura de red un poco más? (¿Internet salvaje? ¿En la misma máquina? ¿En algún punto intermedio?) ¿Ocurre todo el tiempo? O intermitentemente?
Stu Thompson

Respuestas:

116

Hay varias causas posibles.

  1. El otro extremo ha restablecido 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 al escribir en una conexión que el otro extremo ya se ha cerrado normalmente. En otras palabras, un error de protocolo de aplicación.

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

  4. En Windows, "el software causó la cancelación de la conexión", que no es lo mismo que el "restablecimiento de la conexión", es causado por problemas de red que se envían desde su extremo. Hay un artículo de Microsoft Knowledge Base sobre esto.

Marqués de Lorne
fuente
@MattLyons Gracias. Hay artículos de MSDN mucho mejores que eso. Francamente, me parece difícil de creer. Ni siquiera existirá una conexión hasta que se hayan establecido las direcciones IP de origen y destino correctas. Los artículos de MSDN que he visto se refieren a errores de red persistentes que exceden el tiempo de espera de la conexión.
Marqués de Lorne
48

El restablecimiento de la conexión simplemente significa que se recibió un TCP RST. Esto sucede cuando su compañero recibe datos que no puede procesar, y puede haber varias razones para ello.

Lo más simple es cuando cierra el socket y luego escribe más datos en la secuencia de salida. Al cerrar el zócalo, le dijiste a tu compañero que habías terminado de hablar, y puede olvidarse de tu conexión. Cuando envía más datos en ese flujo de todos modos, el igual lo rechaza con un RST para hacerle saber que no está escuchando.

En otros casos, un cortafuegos intermedio o incluso el host remoto en sí podría "olvidarse" de su conexión TCP. Esto podría suceder si no envía ningún dato durante mucho tiempo (2 horas es un tiempo de espera común) o porque el par se reinició y perdió su información sobre las conexiones activas. El envío de datos en una de estas conexiones inactivas también causará un RST.


Actualización en respuesta a información adicional:

Eche un vistazo de cerca a su manejo de SocketTimeoutException. Esta excepción se genera si se excede el tiempo de espera configurado mientras está bloqueado en una operación de socket. El estado del socket en sí no cambia cuando se lanza esta excepción, pero si su controlador de excepción cierra el socket y luego intenta escribir en él, estará en una condición de restablecimiento de conexión. setSoTimeout()está destinado a darle una manera limpia de salir de una read()operación que de otra manera podría bloquearse para siempre, sin hacer cosas sucias como cerrar el socket de otro hilo.

erickson
fuente
No es correcto en varios aspectos. La recolección de basura y las salidas del proceso causan cierres adecuados, no reinicios, pero un cierre seguido de una escritura por parte del par puede inducir un reinicio en lugar de un EOS. Las SocketTimeoutExceptions solo se generan si el lector ha establecido un tiempo de espera de lectura.
Marqués de Lorne
Y no siempre significa que se recibió un RST. También puede significar que uno fue generado por este lado.
Marqués de Lorne
17

Cada vez que he tenido problemas extraños como este, generalmente me siento con una herramienta como WireShark y miro los datos sin procesar que se pasan de un lado a otro. Es posible que se sorprenda de dónde se desconectan las cosas y solo se le notificará cuando intente leer.

GEOCHET
fuente
9

Es vergonzoso decirlo, pero cuando tuve este problema, fue simplemente un error que estaba cerrando la conexión antes de leer todos los datos. En los casos en que se devolvieron pequeñas cadenas, funcionó, pero eso probablemente se debió a que toda la respuesta estaba almacenada antes de cerrarla.

En caso de que se devuelva una cantidad mayor de texto, se produjo la excepción, ya que más de un búfer regresaba.

Puede verificar este descuido. Recuerde que abrir una URL es como un archivo, asegúrese de cerrarla (liberar la conexión) una vez que se haya leído por completo.

Scott S
fuente
9

Debes inspeccionar el rastro completo con mucho cuidado,

Tengo una aplicación de socket de servidor y arreglé un java.net.SocketException: Connection reset caso.

En mi caso, sucede mientras leo de un cliente Socket objeto que está cerrado su conexión por alguna razón. (Red perdida, cortafuegos o aplicación bloqueada o cierre previsto)

En realidad, estaba restableciendo la conexión cuando recibí un error al leer este objeto Socket.

Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

Lo interesante es que for my JAVA Socketsi un cliente se conecta a mi ServerSockety cierra su conexión sin enviar nada se is.read()llama recursivamente. Parece que debido a que está en un bucle while infinito para leer desde este socket, intenta leer desde una conexión cerrada. Si usa algo como el siguiente para la operación de lectura;

while(true)
{
  Receive();
}

Luego obtienes un stackTrace algo como abajo una y otra vez

java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)

Lo que hice fue cerrar ServerSocket y renovar mi conexión y esperar más conexiones entrantes de clientes

String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

Esto restablece mi conexión por pérdidas de socket de cliente desconocido

private void tryReConnect()
        {
            try
            {
                ServerSocket.close();
                //empty my old lost connection and let it get by garbage col. immediately 
                clientSocket=null;
                System.gc();
                //Wait a new client Socket connection and address this to my local variable
                clientSocket= ServerSocket.accept(); // Waiting for another Connection
                System.out.println("Connection established...");
            }catch (Exception e) {
                String message="ReConnect not successful "+e.getMessage();
                logit();//etc...
            }
        }

No pude encontrar otra manera porque, como puede ver en la imagen de abajo, no puede entender si la conexión se pierde o no sin una try and catch, porque todo parece estar bien. Obtuve esta instantánea mientras recibía Connection resetcontinuamente.

ingrese la descripción de la imagen aquí

Davut Gürbüz
fuente
6

Yo tenía el mismo error. Encontré la solución para el problema ahora. El problema era que el programa cliente estaba terminando antes de que el servidor leyera las transmisiones.

kml_ckr
fuente
Eso no causaría esta excepción por sí solo.
Marqués de Lorne
lo haría si System.exit (0) mata el programa y nadie llama a socket.close () ya que la conexión está en mal estado y no se cerró correctamente. taaaan más correctamente dijo que tenía un programa de cliente que se cerró sin cerrar los sockets;) lo cual es algo malo y debe repararse.
Dean Hiller el
1
@DeanHiller No, no lo haría. El sistema operativo cerraría el socket de la misma manera que debería hacerlo la aplicación.
Marqués de Lorne
@EJP ... No estoy seguro ... Solo sé que podríamos reproducirlo con System.exit pero no recuerdo el OS / config ya que eso fue hace bastante tiempo ... llamando a socket.close ( ) en el servidor impidió el restablecimiento de la conexión y se comportó más correctamente.
Dean Hiller
2
@DeanHiller El proceso de lectura finalizó antes de que el proceso de escritura terminara de escribir.
Marqués de Lorne
4

Tuve este problema con un sistema SOA escrito en Java. Estaba ejecutando tanto el cliente como el servidor en diferentes máquinas físicas y funcionaron bien durante mucho tiempo, luego esos reajustes de conexión desagradables aparecieron en el registro del cliente y no había nada extraño en el registro del servidor. Reiniciar tanto el cliente como el servidor no resolvió el problema. Finalmente descubrimos que el montón en el lado del servidor estaba bastante lleno, así que aumentamos la memoria disponible para la JVM: ¡problema resuelto! Tenga en cuenta que no había OutOfMemoryError en el registro: la memoria era escasa, no estaba agotada.

Pino
fuente
2

Verifique la versión de Java de su servidor. Me sucedió porque mi Weblogic 10.3.6 estaba en JDK 1.7.0_75 que estaba en TLSv1. El punto final de descanso que intentaba consumir era cerrar cualquier cosa por debajo de TLSv1.2.

Por defecto, Weblogic intentaba negociar el protocolo compartido más fuerte. Consulte los detalles aquí: Problemas con la configuración de la propiedad del sistema https.protocols para conexiones HTTPS .

Agregué un registro SSL detallado para identificar el TLS compatible. Esto indicaba que TLSv1 se estaba utilizando para el apretón de manos.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Resolví esto enviando la función a nuestro producto compatible con JDK8, JDK8 por defecto es TLSv1.2. Para aquellos restringidos a JDK7, también probé con éxito una solución alternativa para Java 7 al actualizar a TLSv1.2. Usé esta respuesta: Cómo habilitar TLS 1.2 en Java 7

Sumiya
fuente
muchas gracias, me muestras una nueva dirección para solucionar mi problema. y finalmente encontré que es el caso !!!
karl li
1

También tuve este problema con un programa Java que intentaba enviar un comando en un servidor a través de SSH. El problema fue con la máquina ejecutando el código Java. No tenía permiso para conectarse al servidor remoto. El método write () funcionaba bien, pero el método read () arrojaba java.net.SocketException: restablecimiento de la conexión. Solucioné este problema al agregar la clave SSH del cliente a las claves conocidas del servidor remoto.

pmartin8
fuente
0

En mi experiencia, a menudo encuentro las siguientes situaciones;

  1. Si trabaja en una empresa corporativa, comuníquese con el equipo de redes y seguridad. Porque en las solicitudes realizadas a servicios externos, puede ser necesario dar permiso para el punto final relevante.

  2. Otro problema es que el certificado SSL puede haber expirado en el servidor donde se ejecuta su aplicación.

bmck
fuente