API de socket Java: ¿Cómo saber si se ha cerrado una conexión?
Tengo algunos problemas con la API del socket Java. Estoy intentando mostrar la cantidad de jugadores actualmente conectados a mi juego. Es fácil determinar cuándo se ha conectado un jugador. Sin embargo, parece innecesariamente difícil determinar cuándo un jugador se ha desconectado utilizando la API del socket.
La llamada isConnected()
a un enchufe que ha sido desconectado de forma remota siempre parece volver true
. De manera similar, llamar isClosed()
a un socket que se ha cerrado de forma remota siempre parece regresar false
. He leído que para determinar realmente si un socket se ha cerrado o no, se deben escribir datos en el flujo de salida y se debe detectar una excepción. Esta parece una forma realmente sucia de manejar esta situación. Tendríamos que enviar constantemente mensajes basura a través de la red para saber cuándo se cerró un socket.
hay alguna otra solucion?
No existe una API TCP que le indique el estado actual de la conexión. isConnected()
y isClosed()
decirle el estado actual de su socket . No es lo mismo.
isConnected()
le indica si ha conectado este enchufe . Lo has hecho, por lo que devuelve verdadero.isClosed()
le indica si ha cerrado este socket. Hasta que lo hagas, devuelve falso.Si el par ha cerrado la conexión de forma ordenada
read()
devuelve -1readLine()
devolucionesnull
readXXX()
lanzaEOFException
para cualquier otro XXX.Una escritura arrojará un mensaje
IOException
: 'restablecimiento de conexión por parte del par', eventualmente, sujeto a retrasos en el almacenamiento en búfer.
Si la conexión se ha interrumpido por cualquier otro motivo, una escritura generará un
IOException
, eventualmente, como se indicó anteriormente, y una lectura puede hacer lo mismo.Si el interlocutor todavía está conectado pero no utiliza la conexión, se puede utilizar un tiempo de espera de lectura.
Al contrario de lo que puedas leer en otros lugares,
ClosedChannelException
no te dice esto. [Tampoco lo haceSocketException: socket closed.
] Solo te dice que cerraste el canal y luego continuaste usándolo. En otras palabras, un error de programación por tu parte. No indica una conexión cerrada.Como resultado de algunos experimentos con Java 7 en Windows XP, también parece que si:
- estás seleccionando
OP_READ
select()
devuelve un valor mayor que cero- el asociado
SelectionKey
ya no es válido (key.isValid() == false
)
significa que el par ha restablecido la conexión. Sin embargo, esto puede ser peculiar de la versión o plataforma JRE.
- estás seleccionando
Es una práctica general en varios protocolos de mensajería seguir latiendo entre sí (seguir enviando paquetes de ping); no es necesario que el paquete sea muy grande. El mecanismo de sondeo le permitirá detectar al cliente desconectado incluso antes de que TCP lo detecte en general (el tiempo de espera de TCP es mucho mayor). Envíe un sondeo y espere unos 5 segundos para recibir una respuesta; si no ve una respuesta, digamos 2 o 3 Sondeos posteriores, su reproductor se desconecta.
Además, pregunta relacionada