¿Cómo informan los sockets de TCP / IP de Java el éxito o el fracaso de la transmisión a la aplicación?

Tengo un problema con los sockets de TCP / IP de Java: mi aplicación Java continuará sin cesar para enviar datos a un servidor incluso si el servidor se apaga (sin una desconexión de TCP / IP adecuada) mientras tanto.

Estoy usando el siguiente código para enviar los datos:

PrintWriter out = PrintWriter(socket.getOutputStream(), true); out.write("text"); if (out.checkError()) { System.err.println("Error sending string!"); } 

En otra pregunta de desbordamiento de stack , encontré la siguiente respuesta:

TCP / IP (y, por lo tanto, java sockets) garantizará que usted envíe los datos con éxito O que obtenga un error (excepción en el caso de Java) eventualmente.

¿Es mi código suficiente para informarme acerca de que la stack TCP / IP no puede enviar mi cadena con éxito o debo hacer algo adicional?

Btw: ¿fue correcto abrir una nueva pregunta aunque la otra pregunta fue similar? No respondió a mi pregunta satisfactoriamente y solo pude agregar una nueva respuesta, no un nuevo comentario.

Es posible que tenga dos problemas: PrintWriter es una bestia extraña en el mundo de Java Stream / Reader / Writer que se traga las excepciones y requiere que verifique explícitamente que no haya errores.

El único uso para esto (en mi opinión) son las secuencias estándar ( System.out y System.err ), donde la falla en la escritura de la salida no debe detener la aplicación (por ejemplo, si no hay una salida estándar disponible).

Reemplace eso con un OutputStreamWriter y se le informará acerca de los errores tan pronto como Java los conozca.

Eso me lleva al segundo problema posible: TCP / IP no tiene ningún paquete automatizado de mantenimiento de vida: por lo tanto, si su conexión se corta de alguna manera, no lo notará hasta que intente enviar datos.

Entonces, si se conecta a algún zócalo, envía algunos paquetes, espera un poco y luego se desconecta, solo se le notificará cuando la próxima vez intente enviar algunos datos. Esto es inherente al protocolo TCP / IP y no es culpa de Java.

Si desea reducir el problema, puede enviar mensajes periódicos de keep-alive / ping sin efecto real, excepto que verifican si la conexión aún está activa.

Tu pregunta es lo suficientemente diferente como diría yo. Sin embargo, Google tiene mucho que decir sobre este tipo de cosas. Los keep-alives ( SO_KEEPALIVE ) no están diseñados para este tipo de cosas. Por lo que he leído, la especificación de TCP dice que no deben enviarse más de una vez cada dos horas y que depende de su sistema operativo gestionarlo para que no tenga mucho control. Destaco por lo que he leído .

Sin embargo, si usted puede usarlos más de una vez cada dos horas, no importa en su caso, ya que está enviando datos continuamente. Keep-alives solo es necesario si desea detectar una conexión rota mientras no está enviando datos.

Si estuviera utilizando directamente OutputStream of the Socket , se produciría una excepción cuando intente enviar a un destino no disponible (por el motivo que sea). Ya que está utilizando PrintWriter , necesita verificar los errores manualmente usando checkError() .

Entonces, en resumen: sí, es suficiente para su propósito.

Lo que no mencioné (ya que pensé que no era relevante en ese momento) es que estoy tratando de hacer esto en Android.

Sin embargo, después de varias semanas de pruebas, parece que la implementación de las clases estándar de redes Java en Android se está comportando de manera muy diferente a la de Oracle JRE. En Android, es aparentemente imposible detectar de manera confiable si la conexión se ha cerrado, incluso si la cerré yo mismo. [Stream].write() intentará escribir durante varios minutos. Entonces, en Android, parece que siempre tendrás que enviar tus propios keep-alives (¡y comprobar la recepción!) Para detectar una conexión rota.

Las otras respuestas a esta pregunta funcionarán bien con Oracle JRE. ¡Gracias de nuevo!

Si alguien puede proporcionar más información sobre este tema, por favor hágalo.

A veces, aunque el servidor haya muerto, su aplicación cliente no está informada al respecto. Por lo general, este es un enrutador defectuoso en algún lugar que no puede cerrar ambos lados de la conexión. Debe configurar keep-alives para que pueda detectar este tipo de falla.

Dependiendo de su sistema operativo, hay formas de cambiar el intervalo de prueba de mantener la vida.

Se aplica una condición especial al cerrar el zócalo. Dependiendo del socket opt SO_LINGER (ver este artículo ) establecido, la llamada close() retornará inmediatamente o esperará hasta que todas las transmisiones TCP pendientes hayan tenido éxito o se haya producido un error, que luego es señalado por una IOException lanzada desde el close() implementación.

Además, SO_TIMEOUT tiene un efecto en el tiempo de espera de los rebashs.