2009-11-01 5 views
2

J'ai une application qui gère plusieurs connexions de socket Java à différents types de machines distantes (certains PC, d'autres sont des périphériques intégrés). Ces sockets et flux ne doivent pas se fermer indéfiniment, sauf pour une très bonne raison (par exemple, panne d'un système distant).Les flux de socket Java se terminent de manière inattendue

Je rencontre fréquemment un problème où le flux d'entrée se termine de manière inattendue, sans aucune raison (la valeur est -1), c'est-à-dire que la machine distante ne signale pas une interruption de connexion. Mais quand je rejette ces -1 lectures et continue la lecture du flux, la machine distante envoie réellement de nouvelles données plus tard. Cela peut durer très longtemps. Je peux aussi écrire dans le flux de sortie aussi.

Dans la situation actuelle, j'ai le choix entre traiter -1 comme fin de flux et fermer le socket (avec des faux positifs), ou ignorer -1 entrée et risque de ne pas être averti des déconnexions réelles.

Je n'ai pas réussi à créer un exemple de ce problème et les problèmes apparaissent de manière aléatoire.

Des idées quel est le problème?

Edité pour ajouter: Le point de terminaison Java est une réécriture d'une application VB existante qui n'avait pas ces problèmes (du moins à ma connaissance).

+2

Je pense que jeter un coup d'œil à votre source serait utile. –

+1

Merci, mais comme je l'ai dit, je n'ai pas encore créé un exemple simple et efficace du problème, et tout cela est beaucoup trop de code. –

+0

"Trop de code", peut faire partie de votre problème. Cela ne devrait pas être si compliqué. –

Répondre

0

Vérifiez les routeurs au début. Il est courant pour les routeurs bon marché, en particulier ceux qui effectuent le NAT, qu'ils nettoient leurs tables de connexion de temps en temps, ce qui rend vos connexions obsolètes.

Dans tous les cas, votre application devrait être robuste contre ces choses (elles se reproduiront), et vous pouvez l'aider en envoyant régulièrement des paquets sans valeur commerciale sur le fil.

+0

Je fais. Les messages "keep alive" sont définis et utilisés, mais n'aident pas. Le problème est également apparu une fois lorsque j'ai exécuté un serveur et un client sur la même machine. –

+0

Aussi, comme je l'ai dit, si j'ignore le -1, cela fonctionne comme un charme au moins pendant plusieurs heures. –

-1

Il y a apparemment quelques problèmes de réseau dans votre environnement, et vous pouvez essayer de les traquer, mais pour l'instant, il est plus sûr de de fermer le flux et de le rouvrir. C'est ce que l'API assume.

+0

'Problèmes de réseau' ne provoque pas 'read()' pour retourner -1. La seule chose qui peut éventuellement causer cela est la réception d'un segment juridique FIN. – EJP

0

Avez-vous déjà utilisé Wireshark? Il est très facile à configurer et peut vous informer si quelque chose d'inhabituel se passe avec la conversation TCP lorsque cela se produit.

J'avais quelque chose de similaire à votre problème une fois et je l'ai résolu en envoyant un message ping chaque minute entre le serveur et le client. (Il s'est avéré par la suite qu'un problème de pare-feu fermait parfois la moitié de la connexion si aucun trafic ne l'avait traversé pendant 10 minutes.)

Je sais que vous faites des messages KeepAlive mais il est possible que quelque chose se passe le long de la route. ne pas les soutenir. Si vous envoyez votre propre message ping avec quelques octets, vous pouvez être sûr. Je capturerais les paquets réels aux deux extrémités avec Wireshark dans les deux cas pour m'assurer que les messages KeepAlive arrivent vraiment jusqu'au point de terminaison.

+0

Je n'envoie pas tcp keepalive, ce sont des messages d'affaires réels "vides" comme Thorbjørn a suggéré de faire en sorte qu'au moins un message soit envoyé au moins toutes les dix minutes. Moins est difficile parce que le tout doit également fonctionner sur des réseaux mobiles 3G plutôt chers, donc je dois aussi garder le nombre d'octets faible. –

+0

Ah, si vous envoyez de vrais paquets à 0 octets de la couche application à la couche application, je suppose que ce n'est pas le cas. Vous pouvez l'essayer avec une fréquence de 1 minute juste en dev pour l'exclure même si ce n'est pas une solution pratique pour prod. Mais j'ai également manqué où vous avez dit que c'était arrivé en courant sur la même machine. J'essaierais de reproduire ça en premier. Pas besoin de perdre du temps avec wireshark et la mise en réseau si cela peut arriver sur la même machine. –

1

Si vous obtenez -1 signifiant que le flux est fermé, vous ne pouvez pas lire au-delà et trouver plus de données. Une fois qu'un flux est fermé, il ne peut plus être lu.

Il semble que vous exécutiez read() et que vous transtypiez cet octet en octet. Cela signifie que vous ne pouvez pas faire la différence entre une valeur de 255 (que vous pouvez lire au-delà) et une valeur de flux de -1 (que vous ne pouvez pas)

+1

Je ne convertis pas le résultat de l'opération stream.read() en byte. Je sais ce que les docs disent. Si j'ignore juste -1 et réessaye de lire 100 millisecondes plus tard, et que je le répète indéfiniment, de nouvelles données arrivent finalement. C'est fou, mais ça fonctionne vraiment. –

+0

Il est possible que ce comportement soit la conséquence de la superposition d'un flux sur une socket (qui au niveau du système d'exploitation fournit sa propre sémantique de flux). Cependant, étant donné que le Bug Parade n'a pas de rapports de comportement similaire, je soupçonnerais le code de l'OP avant de soupçonner Java. – kdgregory

Questions connexes