7
votes

Java Socket ne jette pas d'exceptions sur une prise morte?

Nous avons une architecture de serveur client simple entre notre appareil mobile et notre serveur tous deux écrit en Java. Une mise en œuvre extrêmement simple et une mise en oeuvre. Cependant, un problème est que lorsque le client se termine brusquement (sans fermer correctement la prise), le serveur ne sait pas qu'il est déconnecté. De plus, le serveur peut continuer à écrire sur cette prise sans obtenir d'exceptions. Pourquoi?

Selon la documentation Les sockets Java devraient lancer des exceptions si vous essayez d'écrire sur une prise qui n'est pas accessible à l'autre extrémité!


0 commentaires

5 Réponses :


0
votes

Les communications TCP / IP peuvent être très étranges. TCP réessayera pendant un certain temps aux couches inférieures de la pile sans jamais laisser les couches supérieures savent que quelque chose s'est passé.

Je m'attendrais pleinement à cela après une certaine période (30 secondes à quelques minutes), vous devriez voir une erreur, mais je n'ai pas testé cela, je vais simplement sortir de la manière dont les applications TCP ont tendance à travailler.

Vous pourriez être capable de resserrer les spécifications TCP (réessayez, le délai d'attente, etc.), mais encore une fois, je n'ai pas beaucoup mal salué.

En outre, il se peut que je suis totalement tort et que la mise en œuvre de Java que vous utilisez est simplement floconneuse.


0 commentaires

2
votes

La connexion sera éventuellement expirée par Retransmit Timeout (RTO). Cependant, le RTO est calculé à l'aide d'un algorithme compliqué basé sur la latence de réseau (RTT), voir cette RFC,

http://www.ietf.org/rfc/rfc2988.txt

Donc sur un réseau mobile, cela peut être minutes. Attendez 10 minutes pour voir si vous pouvez obtenir un délai d'attente.

La solution à ce type de problème consiste à ajouter un battement de cœur dans votre propre protocole d'application et de déchirure de la connexion lorsque vous ne recevez pas ACK pour le battement de coeur.


0 commentaires

1
votes

Le mot clé ici (sans fermer la prise correctement) code>.

Les prises doivent toujours être acquises et éliminées de cette manière: P>

final Socket socket = ...; // connect code

try
{
    use( socket ); // use socket
}
finally
{
    socket.close( ); // dispose
}


0 commentaires

0
votes

Pour répondre à la première partie de la question (à propos de ne pas savoir que le client a déconnecté brusquement), dans TCP, vous ne pouvez pas savoir si une connexion est terminée jusqu'à ce que vous essayiez de l'utiliser.

La notion de La livraison garantie dans TCP est assez subtile: La livraison n'est pas réellement garantie à la demande à l'autre extrémité (cela dépend de ce que signifie vraiment garantie). Section 2.6 de RFC 793 (TCP) donne plus de détails sur ce sujet . Ce fil sur la liste de discussion de la Restlet et Ce fil sur la liste des noyaux Linux pourrait également être d'intérêt.

Pour la deuxième partie (ne détectant pas lorsque vous écrivez sur cette prise), ceci est probablement une question de tampon et de délai d'attente (comme d'autres les ont déjà suggérées).


1 commentaires

J'ai déjà essayé de l'utiliser en écrivant sur la prise et même je ne sais pas si le client a déconnecté.



0
votes

Je suis confronté au même problème. Je pense que lorsque vous enregistrez la prise avec un sélecteur, il ne jette aucune exception. Utilisez-vous un sélecteur avec votre prise?


0 commentaires