Java detecta conexión perdida

Cuando estoy usando, por ejemplo, PuTTY y mi conexión se pierde (o cuando hago una ipconfig /release manual en Windows), responde directamente y notifica que mi conexión se perdió.

Quiero crear un progtwig Java que supervise mi conexión a Internet (a algún servidor confiable), para registrar la fecha / horas en que falla mi internet.

Intenté usar el método Socket.isConnected() , pero eso siempre devolverá “verdadero”. ¿Cómo puedo hacer esto en Java?

Bueno, la mejor manera de saber si su conexión se interrumpe es tratar de leer / escribir desde el socket. Si la operación falla, entonces habrá perdido su conexión en algún momento.

Entonces, todo lo que tiene que hacer es intentar leer en algún intervalo, y si la lectura falla, intente volver a conectarla.

Los eventos importantes para usted serán cuando una lectura falla, perdió la conexión y cuando se conecta una toma nueva, recuperó la conexión.

De esta forma puede realizar un seguimiento del tiempo de actividad y del tiempo de inactividad.

Aunque TCP / IP es un protocolo “orientado a la conexión”, normalmente no se envían datos a través de una conexión inactiva. Puede tener un socket abierto durante un año sin un solo bit enviado por la stack IP. Para notar que se pierde una conexión, debe enviar algunos datos en el nivel de la aplicación. (*) Puede probar esto desconectando el cable del teléfono de su módem ADSL. Todas las conexiones en su PC deben permanecer activas, a menos que las aplicaciones tengan algún tipo de mecanismo keepalive de nivel de aplicación.

Entonces, la única forma de notar la conexión perdida es abrir la conexión TCP a algún servidor y leer algunos datos de ella. Quizás la forma más simple podría ser conectarse a un servidor FTP y buscar un archivo pequeño, o una lista de directorios, de vez en cuando. Nunca he visto un servidor genérico que realmente haya sido diseñado para este caso, y puede que los propietarios del servidor FTP no quieran que los clientes lo hagan.

(*) También hay un mecanismo llamado TCP keepalive, pero en muchos sistemas operativos debe activarlo para todas las aplicaciones, y no es realmente práctico utilizarlo si desea notar la pérdida de conexión rápidamente.

¿Por qué no utilizar el método isReachable() de la clase java.net.InetAddress ?

Cómo funciona esto es la implementación de JVM específica pero:

Una implementación típica usará PETICIONES DE ECO de ICMP si se puede obtener el privilegio; de lo contrario, intentará establecer una conexión TCP en el puerto 7 (Eco) del host de destino.

Si desea mantener una conexión abierta continuamente para que pueda ver cuándo falla, puede conectarse usted mismo al servidor que ejecuta el protocolo ECHO en lugar de hacer que isReachable() haga por usted, leer y escribir datos y esperar a que falle.

Si el cliente se desconecta correctamente, read() devolverá -1, readLine() devuelve null, readXXX() para cualquier otra X arroja EOFException . La única forma confiable de detectar una conexión TCP perdida es escribir en ella. Eventualmente arrojará una ‘reinicio de conexión’ de IOException , pero requiere al menos dos escrituras debido al almacenamiento en búfer.

Es posible que desee intentar mirar el intervalo de tiempo de espera del socket. Con un tiempo de espera corto ( creo que el valor predeterminado es “tiempo de espera infinito”), es posible que pueda atrapar una excepción o algo cuando el host no esté disponible.

De acuerdo, finalmente lo conseguí trabajando con

 try { Socket s = new Socket("stackoverflow.com",80); DataOutputStream os = new DataOutputStream(s.getOutputStream()); DataInputStream is = new DataInputStream(s.getInputStream()); while (true) { os.writeBytes("GET /index.html HTTP/1.0\n\n"); is.available(); Thread.sleep(1000); } } catch (IOException e) { System.out.println("connection probably lost"); e.printStackTrace(); } 

No tan limpio como esperaba, pero no funciona si dejo fuera el os.writeBytes ().

Podrías hacer ping a una máquina cada número de segundos, y esto sería bastante preciso. Tenga cuidado de que no lo haga en DOS.

Otra alternativa sería ejecutar un pequeño servidor en una máquina remota y mantener una conexión con él.

Es probablemente más simple conectarse a yahoo / google o en algún lugar como este.

  URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yc = yahoo.openConnection(); int dataLen = yc.getContentLength() ; 

Neil

El método isConnected() dentro de la clase Socket.java es un poco engañoso. No le dice si el socket está actualmente conectado a un host remoto (como si no estuviera cerrado). En cambio, le dice si el socket alguna vez se ha conectado a un host remoto . Si el socket fue capaz de conectarse al host remoto, este método devuelve true , incluso después de que el socket se haya cerrado. Para saber si un socket está actualmente abierto, debe verificar que isConnected() devuelva true y isClosed() devuelva false . Por ejemplo:

 boolean connected = socket.isConnected() && !socket.isClosed();