API de socket Java: ¿Cómo saber si se ha cerrado una conexión?

Resuelto Dan Brouwer asked hace 12 años • 0 respuestas

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?

Dan Brouwer avatar Apr 20 '12 12:04 Dan Brouwer
Aceptado

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.

  1. isConnected()le indica si ha conectado este enchufe . Lo has hecho, por lo que devuelve verdadero.

  2. isClosed()le indica si ha cerrado este socket. Hasta que lo hagas, devuelve falso.

  3. Si el par ha cerrado la conexión de forma ordenada

    • read()devuelve -1
    • readLine()devolucionesnull
    • readXXX()lanza EOFExceptionpara 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.

  4. 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.

  5. Si el interlocutor todavía está conectado pero no utiliza la conexión, se puede utilizar un tiempo de espera de lectura.

  6. Al contrario de lo que puedas leer en otros lugares, ClosedChannelExceptionno te dice esto. [Tampoco lo hace SocketException: 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.

  7. Como resultado de algunos experimentos con Java 7 en Windows XP, también parece que si:

    • estás seleccionandoOP_READ
    • select()devuelve un valor mayor que cero
    • el asociado SelectionKeyya 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.

user207421 avatar Apr 20 '2012 06:04 user207421

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

Kalpak Gadre avatar Apr 20 '2012 05:04 Kalpak Gadre