Vérifier si une ClientSocket a déconnecté dans java se bloque
C'est un suivi à:
En gros, j'ai un serveur boucle qui gère une connexion à un solitaire client. À un moment donné dans la boucle, si un ClientSocket existe, il tente une lecture pour vérifier si le client est toujours connecté:
if (bufferedReader.read()==-1 ) {
logger.info("CONNECTION TERMINATED!");
clientSocket.close();
setUpSocket(); //sets up the server to reconnect to the client
}else{
sendHeartBeat(); //Send a heartbeat to the client
}
Le problème est, qu'une fois qu'un socket a été créé l'application se bloque sur la lecture, je suppose attente pour les données qui ne viendra jamais, depuis que le client n'envoie jamais sur le serveur. Avant c'était OK, parce que cela correctement traitées se déconnecte (la lecture serait finalement échouer lorsque le client s'est déconnecté), et la boucle serait tenter de rétablir la connexion. Cependant, j'ai maintenant ajouté ci-dessus sendHeartBeat() la méthode, qui, périodiquement, permet au client de savoir que le serveur est encore en place. Si la lecture est tenue le fil puis les battements de cœur de ne jamais arriver!
Donc, je suppose que je suis en train de tester si la connexion est toujours pas correctement. Je pourrais, comme un rapide hack, exécutez la bufferedReader.read() dans un autre thread, mais je vais avoir toutes sortes de problèmes de concurrence que je n'ai vraiment pas envie de traiter avec.
Donc la question est quelques fois:
1) Suis-je vérifier pour un client déconnecter correctement?
2) Si non, comment dois-je faire?
3) Si je le fais correctement comment je puis-je obtenir le lire pour ne pas tenir les processus en otage? Ou est-threading le seul moyen?
OriginalL'auteur Alex | 2009-03-30
Vous devez vous connecter pour publier un commentaire.
Lorsque vous créez votre douille, d'abord définir un délai d'attente:
Avec cela, si un temps de lecture, vous obtiendrez
java.net.SocketTimeoutException
(ce que vous avez à les attraper). Ainsi, vous pourriez faire quelque chose comme cela, en supposant que vous avez déjà réglé l'SO_TIMEOUT comme indiqué ci-dessus, et en supposant que le rythme cardiaque obtiendrez toujours une réponse du système à distance:Une façon courante de ce traitement est de définir le délai d'expiration pour un certain nombre (disons 10 secondes), puis en gardant la trace de la dernière fois que vous avez réussi à lire à partir de la prise. Si 2,5 fois votre délai d'attente écoulé, puis abandonné sur le client et fermer le socket (donc l'envoi d'un paquet FIN de l'autre côté, juste au cas où).
Si le rythme cardiaque va pas obtenir aucune réponse du système à distance, mais est simplement un moyen de l'en fin de compte générer une IOException plus tôt lors de la connexion a chuté vers le bas, alors vous pourriez le faire (en supposant que le sendHeartBeat lui-même ne sera pas jeter un IOException):
J'ai ajouté un exemple de code pour montrer
J'ai amélioré le code exemple pour utiliser plus de votre code.
En fait, la connexion pourrait encore exister dans votre code si rien n'a été envoyée pour le temps > maxTimeout, mais le client est toujours connecté.
Mais dans ce cas, vous aurait envoyé deux battements de coeur avec aucune réponse, alors cela implique que la distance n'est plus en train de parler.
OriginalL'auteur Eddie
Vous de vérifier correctement, vous pouvez ajouter un try catch avec IOException dans le cas où il se produit.
Il y a un moyen pour éviter les threads, vous pouvez utiliser un Sélecteur avec un non-bloking socket.
OriginalL'auteur no_ripcord
Vous devez ajouter la vérification des erreurs dans votre déconnexion de détection. Parfois, une IOException peut être levée lorsque la connexion à l'autre extrémité est perdu.
J'ai peur que le filetage est inévitable ici. Si vous ne voulez pas bloquer l'exécution de votre code, vous devez créer un thread séparé.
Tôt ou tard, vous aurez besoin de thread. Il serait préférable de sortir bufferedReader.lire dans un thread séparé. En fait, tous les socket communications doivent être dans un fil de leur propre.
OriginalL'auteur kgiannakakis