JAVA: Manipulación de desconexión de zócalo.

  1. Dos computadoras están conectadas por conexión de socket. Si el servidor / cliente cierra la conexión desde su extremo (es decir, cierra InputStream , OutputStream y Socket ), ¿cómo puedo informar al otro extremo sobre la desconexión? Hay una forma que conozco: tratar de leer desde InputStream , que lanza una IOException si la conexión está cerrada, pero ¿hay alguna otra forma de detectar esto?
  2. Otra pregunta, busqué el problema en Internet y vi que inputStream.available() no resuelve este problema. ¿Porqué es eso?

Información adicional: Solicito otra forma porque mi proyecto se vuelve difícil de manejar si tengo que intentar leer desde InputStrem para detectar una desconexión.

tratando de leer desde InputStream, que lanza una excepción IOException

Eso no es correcto. Si el par cierra el socket:

  • read() devuelve -1
  • readLine() devuelve null
  • readXXX() lanza la EOFException , para cualquier otra X.

Como InputStream solo tiene métodos de read() , solo devuelve -1: no arroja una IOException en EOS.

Contrariamente a otras respuestas aquí, no hay una API TCP o método Socket que le dirá si el par ha cerrado la conexión. Tienes que intentar una lectura o una escritura.

Deberías usar un tiempo de espera de lectura.

InputStream.available() no resuelve el problema porque no devuelve ninguna indicación de EOS de ningún tipo. Hay pocos usos correctos de este, y este no es uno de ellos.

No hay una forma de OOO de obtener una callback / excepción en el momento en que se interrumpe la conexión. Solo conoce la conexión rota solo cuando realiza una lectura / escritura explícita en el flujo de socket.

Hay dos formas de leer desde un socket a saber. Leer byte por byte de forma sincronizada a medida que llegan; o espere hasta la cantidad deseada de bytes disponibles en el flujo y luego realice una lectura masiva. Haga la comprobación llamando a available () en la secuencia de socket que le proporciona la cantidad de bytes actualmente disponibles para lectura. En el segundo caso, si la conexión de socket se interrumpe por alguna razón, no hay forma de que se le notifique. En ese caso, necesita emplear un mecanismo de tiempo de espera para su espera. En el primer caso donde haces lectura / escritura explícita, obtienes una excepción.

El problema no es “si el servidor / cliente cierra la conexión”. El problema es “¿qué pasa si no cierran la conexión y, sin embargo, se interrumpe la conexión?”

No hay forma de detectar eso sin un protocolo de latido propio.

Otra opción es establecer SO_KEEPALIVE en verdadero.

“Cuando se configura la opción keepalive para un socket TCP y no se han intercambiado datos a través del socket en ninguna dirección durante 2 horas (NOTA: el valor real depende de la implementación)”

En mi experiencia, es mucho más rápido que cada 2 horas. Más como unos ~ 5 minutos. Aparte de usar So_KEEPALIVE, estás atornillado: P

En mis protocolos de comunicaciones, uso un byte de ‘latido’ reservado que se envía cada 2 segundos. Mi propio filterInputStream y filterOutputStream envía / y digiere el byte de latido.

Q1 Si cierra la conexión de socket en el servidor, el cliente debe lanzar una excepción si no inmediatamente, ciertamente en el próximo bash de lectura, y viceversa.

Q2 de los JavaDocs

Devuelve una estimación del número de bytes que pueden leerse (o saltarse) desde este flujo de entrada sin bloquearlos mediante la siguiente invocación de un método para este flujo de entrada. La siguiente invocación podría ser el mismo hilo u otro hilo. Una sola lectura u omisión de estos muchos bytes no se bloqueará, pero puede leer u omitir menos bytes.

Esto no es una indicación del número de bytes actualmente en el flujo, sino una estimación del número de bytes que pueden leerse desde la implementación que no bloqueará el subproceso actual