web-dev-qa-db-fra.com

Java détecte la connexion perdue

Quand j'utilise par exemple PuTTY et ma connexion est perdue (ou lorsque je fais un ipconfig /release manuel sur Windows), il répond directement et informe que ma connexion a été perdue.

Je veux créer un programme Java qui surveille ma connexion Internet (sur un serveur fiable), afin de consigner la date/l'heure à laquelle mon internet tombe en panne.

J'ai essayé d'utiliser la méthode Socket.isConnected() mais cela retournera toujours "true". Comment puis-je faire cela en Java?

24
kresjer

Eh bien, le meilleur moyen de savoir si votre connexion est interrompue est d’essayer de lire/écrire à partir du socket. Si l'opération échoue, vous avez parfois perdu votre connexion.

Donc, tout ce que vous avez à faire est d’essayer de lire à intervalles réguliers et, si la lecture échoue, essayez de vous reconnecter.

Les événements importants pour vous seront les cas où une lecture échoue - vous avez perdu la connexion, et lorsqu'un nouveau socket est connecté - vous avez retrouvé la connexion.

De cette façon, vous pouvez suivre les temps morts et les temps morts.

20
jjnguy

Même si TCP/IP est un protocole "orienté connexion", normalement aucune donnée n'est envoyée via une connexion inactive. Vous pouvez avoir un socket ouvert pendant un an sans qu'un seul bit soit envoyé dessus par la pile IP. Pour constater qu’une connexion est perdue, vous devez envoyer des données au niveau de l’application. (*) Vous pouvez l’essayer en débranchant le câble téléphonique de votre modem ADSL. Toutes les connexions de votre PC doivent rester actives, à moins que les applications ne disposent d’un mécanisme de maintien au niveau de l’application.

Ainsi, le seul moyen de constater une perte de connexion consiste à ouvrir la connexion TCP vers un serveur et à en lire certaines données. Le moyen le plus simple serait peut-être de se connecter à un serveur FTP et d’extraire un fichier de petite taille - ou une liste de répertoires - de temps en temps. Je n'ai jamais vu un serveur générique qui était vraiment destiné à être utilisé dans ce cas, et les propriétaires du serveur FTP peuvent ne pas aimer les clients qui le font.

(*) Il existe également un mécanisme appelé TCP keepalive, mais dans de nombreux systèmes d'exploitation, vous devez l'activer pour toutes les applications. Son utilisation n'est pas très pratique si vous souhaitez détecter rapidement une perte de connexion

11
tputkonen

Si le client se déconnecte correctement, un read() renverra -1, readLine() renverra null, readXXX() pour tout autre X jeté EOFException. Le seul moyen fiable de détecter une connexion perdue TCP consiste à y écrire. Finalement, une IOException 'réinitialisation de la connexion' sera générée, mais il faudra au moins deux écritures en raison de la mise en mémoire tampon.

7
user207421

Pourquoi ne pas utiliser la méthode isReachable() de la classe Java.net.InetAddress?

Comment cela fonctionne est spécifique à l'implémentation JVM mais:

Une implémentation typique utilisera ICMP ECHO REQUEST si le privilège peut être obtenu, sinon elle essaiera d’établir une connexion TCP sur le port 7 (Echo) de l’hôte de destination.

Si vous souhaitez garder une connexion ouverte en permanence pour pouvoir voir quand cela échoue, vous pouvez vous connecter au serveur exécutant le protocole ECHO vous-même plutôt que de laisser isReachable() le faire pour vous, de lire et d'écrire des données et d'attendre son échec.

7
Dave Webb

Bon alors j'ai enfin réussi à travailler avec

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();
}

Pas aussi propre que je l'espérais mais cela ne fonctionnera pas si je laisse de côté l'os.writeBytes ().

1
kresjer

Vous voudrez peut-être essayer de regarder le socket intervalle de délai d'attente . Avec un délai d'expiration court (je crois que, le paramètre par défaut est 'délai d'expiration infini'), vous pourrez peut-être intercepter une exception ou quelque chose lorsque l'hôte devient inaccessible.

1
poundifdef

C'est probablement plus simple de se connecter à yahoo/google ou quelque part comme ça.

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

Neil

0
Neil Wightman

Vous pouvez envoyer une requête ping à une machine toutes les secondes, ce qui est assez précis. Veillez à ce que vous ne l'utilisez pas.

Une autre alternative serait d'exécuter un petit serveur sur une machine distante et de rester connecté à celui-ci.

0
Geo

La méthode isConnected() dans la classe Socket.Java est un peu trompeuse. Il ne vous dit pas si le socket est actuellement connecté à un hôte distant (comme s'il n'était pas fermé). Au lieu de cela, il vous indique si le socket a déjà été connecté à un hôte distant . Si le socket a pu se connecter à l'hôte distant, cette méthode retourne true, même après la fermeture de ce socket. Pour savoir si un socket est actuellement ouvert, vous devez vérifier que isConnected() renvoie true et isClosed() renvoie false. Par exemple:

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