Quelle est la différence entre la connexion et le délai de lecture pour les sockets?

180

3 questions:

  1. Quelle est la différence entre la connexion et le délai de lecture pour les sockets?

  2. Que signifie le délai d'expiration de la connexion défini sur «infini»? Dans quelle situation peut-il rester dans une boucle infinitive? et qu'est-ce qui peut déclencher la mort de la boucle infinie?

  3. Que signifie le délai de lecture défini sur «infini»? Dans quelle situation peut-il rester dans une boucle infinitive? et qu'est-ce qui peut déclencher la mort de la boucle infinie?

corgrath
la source

Réponses:

227

1) Quelle est la différence entre la connexion et le délai de lecture pour les sockets?

Le délai d'expiration de la connexion correspond au délai d'expiration de la connexion initiale; c'est-à-dire terminer la négociation de connexion TCP. Le délai de lecture est le délai d'attente pour lire les données 1 . Plus précisément, si le serveur ne parvient pas à envoyer un octet <timeout> secondes après le dernier octet, une erreur de délai de lecture sera déclenchée.

2) Que signifie le délai d'expiration de la connexion défini sur «infini»? Dans quelle situation peut-il rester dans une boucle infinitive? et qu'est-ce qui peut déclencher la mort de la boucle infinie?

Cela signifie que la tentative de connexion peut potentiellement bloquer pour toujours. Il n'y a pas de boucle infinie, mais la tentative de connexion peut être débloquée par un autre thread fermant le socket. (Un Thread.interrupt()appel peut également faire l'affaire ... pas sûr.)

3) Que signifie le délai de lecture réglé sur «infini»? Dans quelle situation peut-il rester dans une boucle infinie? Qu'est-ce qui peut déclencher la fin de la boucle infinie?

Cela signifie qu'un appel à readsur le flux de socket peut bloquer pour toujours. Encore une fois, il n'y a pas de boucle infinie, mais le readpeut être débloqué par un Thread.interrupt()appel, fermant le socket, et (bien sûr) l'autre extrémité envoyant des données ou fermant la connexion.


1 - Ce n'est pas ... comme le pensait un commentateur ... le délai d'expiration de la durée pendant laquelle un socket peut être ouvert ou inactif.

Stephen C
la source
8

Il s'agit de valeurs de délai d'attente appliquées par la JVM pour l'établissement de la connexion TCP et l'attente de la lecture des données à partir du socket.

Si la valeur est définie sur l'infini, vous n'attendrez pas indéfiniment. Cela signifie simplement que JVM n'a pas de délai d'expiration et que le système d'exploitation sera responsable de tous les délais. Cependant, les délais d'expiration sur le système d'exploitation peuvent être très longs. Sur certains réseaux lents, j'ai vu des délais d'expiration allant jusqu'à 6 minutes.

Même si vous définissez la valeur du délai d'expiration pour le socket, cela peut ne pas fonctionner si le délai d'expiration se produit dans le code natif. On peut reproduire le problème sous Linux en se connectant à un hôte bloqué par le pare-feu ou en débranchant le câble sur le switch.

La seule approche sûre pour gérer le délai d'expiration TCP consiste à exécuter le code de connexion dans un thread différent et à interrompre le thread lorsqu'il prend trop de temps.

Codeur ZZ
la source
"Si la valeur est définie sur l'infini, vous n'attendrez pas indéfiniment." Tant qu'il ne s'agit pas de discuter de la signification de «l'infini», il peut certainement arriver que vous attendiez très très longtemps. Nous avons eu un cas ici, où un HttpURLConnection.getResponseCode()était suspendu pour apprx. une semaine avant de redémarrer le processus. Il n'y avait évidemment pas de timeout défini du côté JVM et pas de timeout du côté Linux OS.
Tom Fink
Le dernier paragraphe n'est pas correct. Une connexion expirera après environ une minute au plus. Un thread séparé est complètement inutile. Vous pouvez certainement avoir des lectures qui s'exécutent indéfiniment s'il n'y a pas de données. Cependant, le Javadoc se trompe sur le fait que le délai de connexion par défaut est infini. Ça ne l'est pas.
Marquis of Lorne
1
@comeGetSome Ce n'est pas correct. Vous pouvez arrêter la prise pour l'entrée. Cela fera en sorte que la lecture bloquée rencontre la fin du flux.
Marquis de Lorne
@comeGetSome: J'ai dû implémenter cela en utilisant un thread qui contient une référence à une connexion URL HTTP ouverte. Lorsque ledit thread ferme la connexion, l'autre thread lance "java.net.SocketException: Socket fermé". Merci au bug JDK-8075484 de m'avoir fait faire ça!
fmcato
@comeGetSome Vous pouvez sûrement appeler Socket.shutdownInput()sans avoir votre main? NB Ces délais sont appliqués par TCP, pas par la JVM.
Marquis de Lorne