web-dev-qa-db-fra.com

=java socket / sortie flux écrit: bloquent-ils?

Si je n'écris que dans une prise sur un flux de sortie, il bloquera-t-il déjà? Lit uniquement peut bloquer, non? Quelqu'un m'a dit que les écrivies peuvent bloquer mais je ne vois qu'une fonctionnalité de délai d'attente pour le procédé de lecture d'une prise - Socket.setSoTimeout().

Cela n'a pas de sens pour moi qu'une écriture pourrait bloquer.

36
jbu

Une écriture sur une prise peut également bloquer, surtout s'il s'agit d'une prise TCP. Le système d'exploitation tamponnera une certaine quantité de données non transmises (ou transmises mais non reconnues). Si vous écrivez des objets plus rapidement que l'application distante est capable de le lire, la prise sauvegardera éventuellement vos appels write bloquera.

Répondre à ces questions de suivi:

Alors, y a-t-il un mécanisme pour définir un délai d'attente pour cela? Je ne suis pas sûr de quel comportement aurait-il ... peut-être jeter les données si les tampons sont pleins? Ou éventuellement supprimer des données plus anciennes dans le tampon?

Il n'y a pas de mécanisme pour définir un délai d'écriture sur un java.net.socket. Il y a une méthode Socket.setSoTimeout(), mais elle affecte accept() et read() appels ... et non write() appels. Apparemment, vous pouvez obtenir des délais d'écriture si vous utilisez un mode Nio, non bloquant et un sélecteur, mais cela n'est pas aussi utile que vous pourriez imaginer.

Une pile correctement implémentée TCP _ _ ne jette pas les données tamponnées à moins que la connexion soit fermée. Toutefois, lorsque vous obtenez un délai d'écriture, il est incertain que les données actuellement dans les tampons de niveau du système d'exploitation ont été reçues par l'autre extrémité ... ou non. L'autre problème est que vous ne savez pas à quel point les données de votre dernier write ont été transférées au niveau du système d'exploitation TCP tampons de pile. Absent du protocole de niveau d'application pour resynoncer le flux*, la seule chose sûre à faire après un délai d'attente sur write est d'arrêter la connexion.

En revanche, si vous utilisez une prise UDP, write() Les appels ne bloqueront pas de temps significatif. Mais l'inconvénient est que s'il ya des problèmes de réseau ou que l'application distante ne se précipite pas, les messages seront supprimés sur le sol sans notification à l'une ou l'autre extrémité. De plus, vous pouvez trouver que les messages sont parfois livrés à la demande distante en panne. Ce sera à vous (le développeur) de traiter ces problèmes.

* Il est théoriquement possible de le faire, mais pour la plupart des applications, il n'est pas logique de mettre en œuvre un mécanisme de resynchronisation supplémentaire au-dessus d'un flux TCP/IP déjà fiable (à un point). Et si cela a eu un sens, vous auriez également besoin de faire face à la possibilité que la connexion soit fermée ... de sorte qu'il serait plus simple de supposer IT Fermé.

49
Stephen C

Le seul moyen de le faire est d'utiliser Nio et Selectors.

Voir l'écriture de l'ingénieur Sun/Oracle dans ce rapport de bogue: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=40311

7
Noel Grandin