6
votes

Comment les sockets Java TCP / IP signalent-ils le succès de la transmission ou l'échec de la demande?

J'ai un problème avec Java TCP / IP Sockets: My Java Application se poursuivra sans fin d'envoyer des données à un serveur même si le serveur est désactivé (sans déconnecter TCP / IP correctement) pendant l'entre-temps.

J'utilise le code suivant pour envoyer les données: xxx

dans Une autre question de dépassement de pile , j'ai trouvé la réponse suivante:

TCP / IP (et là-bas des sockets Java) vous garantira que vous soit envoyer avec succès les données ou obtenir un Erreur (exception dans le cas de Java) éventuellement.

est mon code suffisant pour être informé de la pile TCP / IP de ne pas pouvoir envoyer mon chaîne avec succès ou dois-je faire quelque chose en plus?

BTW: C'était-il correct de ouvrir une nouvelle question même si l'autre question était similaire? Il n'a pas répondu à ma question de manière satisfaisante et je n'ai pas pu ajouter une nouvelle réponse, pas un nouveau commentaire.


1 commentaires

Premièrement, pensez-vous que je vous ai aimé, c'est ... Votre nom Tajmahal :). Deuxièmement, vous pouvez poser autant de questions que vous le souhaitez comme libre et ouvert. Mais vous ne devriez pas. Si vous trouvez une question similaire, essayez de trouver une solution pour votre version. Si de toute façon ce n'est pas possible, faites-le comme vous l'avez fait. Reportez-vous à une autre question ce que vous avez déjà vu, mettez ici ce que vous avez essayé et l'endroit où vous pensez être coincé. Stackoverflow Guy est génial si vous avez une véritable question / bonne question. Sinon, votre question peut être fermée / déplacée / évacuée, etc., etc. J'ai suscressé tout ce que :-)


5 Réponses :


0
votes

Parfois, même si le serveur est mort, votre application client n'est pas informée à ce sujet. Habituellement, c'est un mauvais routeur quelque part omis de fermer les deux côtés de la connexion. Vous devriez configurer Garder-Alives Vous pouvez donc détecter ce type d'échec.

Selon votre OS, il existe des moyens de modifier l'intervalle de test de conservation.


0 commentaires

4
votes

Vous pourriez avoir deux problèmes: imprimeur est une étrange bête dans le flux Java / lecteur / écrivain monde en ce sens qu'il avale des exceptions et vous oblige à vérifier explicitement des erreurs.

La seule utilisation pour cela (à mon avis) sont les flux standard ( system.out et system.err ), où l'échec de l'écriture de la sortie ne doit pas arrêter le application (par exemple, si aucune sortie standard n'est disponible).

Remplacez celui-ci avec un sortiestreamwriter et vous serez informé des erreurs dès que Java en connaît à leur sujet.

Cela m'amène au deuxième problème possible: TCP / IP n'a pas de paquets de conservation automatisés: donc si votre connexion est coupée d'une manière ou d'une autre, vous ne le remarquerez pas réellement jusqu'à ce que vous essayiez d'envoyer des données.

Donc, si vous vous connectez à une prise, envoyez des paquets, attendez un peu et puis est déconnecté, vous ne serez informé que du fait que vous essayez ensuite d'envoyer des données. Ceci est inhérent au protocole TCP / IP et non à la faute de Java.

Si vous souhaitez réduire le problème, vous pouvez envoyer des messages périodiques de conservation / ping sans effet réel, sauf qu'ils vérifient si la connexion est toujours en vie.


2 commentaires

Mais si je débranche le câble réseau sur le serveur et continue à envoyer un message chaque seconde, combien de temps devrait-il prendre out.CheckError () pour savoir que la transmission a été infructueuse? Secondes? Minutes? Les heures?


J'ai remplacé l'imprimeur avec une sortie de sortie, mais je peux toujours débrancher le câble réseau et transmettre des âges sans obtenir une exception.



1
votes

Votre question est assez différente, je dirais. Google a beaucoup à dire à propos de ce genre de chose. Les conservateurs ( SO_EEKEKALIVE ) ne sont pas conçus pour ce type de chose. D'après ce que j'ai lu la spécification TCP dit qu'ils devraient pas être envoyés plus d'une fois toutes les deux heures et que votre système d'exploitation est à la hauteur de le gérer afin que vous n'ayez pas beaucoup de contrôle. Je souligne de ce que j'ai lu .

Que vous puissiez les utiliser plus d'une fois toutes les deux heures que possible dans votre cas, car vous envoyez continuellement des données. Les conservations ne sont nécessaires que si vous souhaitez détecter une connexion cassée pendant que vous n'envoyez pas de données.

Si vous utilisiez le de sortie de la prise directement, il lancerait une exception lorsque vous essayez d'envoyer une destination indisponible (pour une raison quelconque pouvant être). . Puisque vous utilisez imprimeur , vous devez rechercher des erreurs manuellement à l'aide de CheckError () .

Donc, en résumé: oui, il suffit à votre but.


2 commentaires

Alors pourquoi ne travaille-t-il pas pour moi? Je peux débrancher le câble sur le serveur et continuer à envoyer des données pour minutes sans obtenir une erreur. J'envoie actuellement un message chaque seconde. La pile TCP / IP ne doit-elle pas remarquer les acks manquants et informer la couche d'application?


Oui, ça devrait. Essayez d'utiliser directement la sortie directement et voyez si cela améliore les choses pour vous: socket.getoutoutputtream (). Écrire ("Texte" .tobytes ()); . Il devrait jeter une exception. Ou utiliser la classe @joachim suggérées. Si j'ai vu sa réponse, je n'aurais probablement pas dérangé l'écriture de la mienne.



0
votes

Une condition spéciale s'applique lorsque vous fermez la prise. Selon le socket OPT SO_LINGER (voir cette article ) Vous définissez, le fermeture () L'appel reviendra immédiatement ou attendez que toutes les transmissions TCP en attente ont été réussies ou une erreur se produisait, ce qui est ensuite signalé par une IOException jeté de la ferme () implémentation.

Aussi so_timeout a un effet sur lorsque les tentatives seront tirées.


0 commentaires

1
votes

Ce que je n'ai pas mentionné (comme je pensais que ce n'était pas pertinent à ce moment-là) est que j'essaie de le faire sur Android.

Après plusieurs semaines de test, il semble que la mise en œuvre de Android des classes de réseau Java standard se comporte très différemment de l'oracle JRE. Sur Android, il est apparemment impossible de détecter de manière fiable si la connexion a été fermée, même si je la fermais moi-même. [flux] .write () va essayer d'écrire pendant plusieurs minutes. Donc, sur Android, il semble que vous devriez toujours envoyer vos propres garderies (et vérifier la réception!) Pour détecter une connexion cassée.

Les autres réponses à cette question fonctionneront bien avec l'oracle JRE. Merci encore!

Si quelqu'un peut fournir des informations supplémentaires sur ce sujet, veuillez le faire.


1 commentaires

Je suis d'accord, les sockets sur Android sont de buggy, ils ne soulèvent souvent aucune exception lorsqu'ils devraient.