2009-12-16 15 views
5

Tengo una aplicación de cliente-servidor con un servidor de Java. Funciona casi perfecto, excepto que después de un período prolongado de tiempo, de repente, un socket sigue colgando. Este socket no es más que uno de muchos, el resto parece estar bien todavía, pero una vez que llega al socket, el servidor simplemente no pasa la línea de envío. Estas son las piezas pertinentes del código:Java - Extraño zócalo colgante?

Socket socket; // A normal socket 
out = new PrintWriter(socket.getOutputStream(), true); // The outstream 
out.println(msg + "\0"); // This command is used to send stuff, msg is a String 

No se lanzan excepciones, la aplicación de línea simplemente no parece conseguir más allá de la línea:

out.println(msg + "\0"); 

sí sé que la cadena es un buen uno, causa 4 o 5 tomas más antes de que este pueda enviarlo bien. También tenga en cuenta que, hasta donde yo sé, este socket podría enviar cientos de mensajes muy bien antes de que se bloquee repentinamente. ¿Alguien tiene una idea de qué tipo de error debería estar buscando?

+0

¿Con qué sistema operativo se está ejecutando? ¿Estás hablando con algo cercano o lejano? – bmargulies

+1

¿comprueba el tamaño de la cola de envío/recepción? Suena como un problema que he experimentado recientemente donde el buffer se llenó y causó que el resto de la conexión se cuelgue. –

+0

¿Estás seguro de que el zócalo tiene un lector activo y no solo está lleno el búfer? – rsp

Respuesta

5

Hay muchas cosas que pueden causar esto, pero parece que probablemente esté retroactivamente a nivel de TCP.

Normalmente, cuando envía datos en un socket, simplemente se almacena en un búfer y la llamada de envío (en su caso, println() y flush()) puede regresar antes de que los datos se envíen a la red. Podría ser que todas sus escrituras anteriores en este socket estuvieran almacenadas en el buzón local SO_SNDBUF y simplemente lo haya llenado.

(1) ¿Puedes rastrear esto usando tcpdump o Wireshark y encontrar la conexión exacta que está colgando (sé que esto se pone difícil con muchas conexiones)? Examinar el tamaño de la ventana TCP en el momento en que cuelga su programa le dirá más sobre si está bloqueando en Java, o en el nivel de la red.

(2) Volcar la pila y publicarla aquí. Los Java Sockets tienen un bloqueo interno para evitar que dos subprocesos les escriban a la vez. ¿Estás seguro de que solo un hilo está accediendo a ese socket en el momento en que intentas escribir?

que debe de intentar hacer una

$ jstack <PID> 

cuando está congelado para ver exactamente donde está colgado, y si el hilo de escritura está tratando de obtener ningún bloqueo.

3

El Socket del objeto OutputStream bloqueará en una escritura en las mismas condiciones que la llamada subyacente send() bloqueará: cuando los buffers de socket local están llenos. Que permanezca bloqueado indica que el buffer de salida no puede vaciarse, lo que a su vez indica que el buffer de lectura en el otro extremo de la conexión está lleno, y que la aplicación que maneja el otro extremo de la conexión no lee datos que ya han llegado .