2009-05-27 8 views
19

Je ne connais pas vraiment les sockets sauf la façon de les lire et d'écrire comme s'il s'agissait de fichiers. Je connais un peu l'utilisation des sélecteurs de socket. Je ne comprends pas pourquoi vous devez rincer une douille, que se passe-t-il réellement là? Les bits traînent quelque part dans la mémoire jusqu'à ce qu'ils soient repoussés? J'ai lu des choses en ligne sur les prises, mais tout est très abstrait et de haut niveau.Qu'est-ce que cela signifie de vider une douille?

Que se passe-t-il ici?

Répondre

42

Il y a un certain nombre de frais généraux liés par écrit à une prise réseau et l'envoi de données. Si des données étaient envoyées chaque fois que l'octet était entré dans le socket, vous obtiendriez 40 octets d'en-tête TCP pour chaque octet de données réelles. (En supposant que vous utilisez une socket TCP, bien sûr, les autres sockets auront des valeurs différentes). Afin d'éviter une telle inefficacité, le socket maintient un tampon local, qui est généralement un peu plus de 1000 octets. Lorsque ce tampon est rempli, un en-tête est enroulé autour des données et le paquet est envoyé à sa destination.

Dans de nombreux cas, vous n'avez pas besoin chaque paquet à être envoyés immédiatement; Si vous transférez un fichier, les premières données peuvent ne pas être utiles sans les données finales du fichier, cela fonctionne donc bien. Si vous devez forcer l'envoi immédiat des données, le vidage du tampon enverra toutes les données qui n'ont pas encore été envoyées.

Notez que lorsque vous fermez une prise, il évacue automatiquement toutes les données remaning, donc il n'y a pas besoin de rincer avant de fermer.

+0

Comment NAGL est-elle liée à cela, le savez-vous? – rogerdpack

+0

bonne réponse .... – goh

1

Je n'ai pas utilisé le flush pour la programmation de socket. Je me souviens quelque part qu'il existe des modes que vous pouvez définir, où les envois orientés flux essaient de réduire le nombre de petits paquets envoyés. Cependant, vous devez utiliser sendall() pour vous assurer que tout ce qui est dans le tampon est envoyé.

La fonction shutdown() est très utile que vous Spooling vers le bas. Bien sûr, vous devez utiliser un appel close() si vous ne voulez pas que des trucs traînent.

Jetez un oeil à Beej's guide pour plus d'informations.

+3

sendall() est la même chose que flush() –

2

L'algorithme de Nagle est souvent utilisé sur les sockets. En un mot, il attend jusqu'à ce qu'il y ait une quantité non-triviale de données à envoyer. Le problème est de parvenir à un équilibre entre la latence de transmission et le coût de l'envoi d'un paquet de données.

Plus la charge utile de données, plus la largeur de bande perdue à cause de l'en-tête est (essentiellement) de taille fixe. De plus, les systèmes intermédiaires ont généralement des limites de performance basées plus significativement sur le débit de paquets, et non sur le débit de données global.

+0

Cette réponse n'aborde pas vraiment le problème du flush d'une socket. –

9

Vous ne pouvez pas vraiment vider une socket.

(De How can I force a socket to send the data in its buffer?)

Vous ne pouvez pas forcer. Période. TCP se fait sa propre idée quant à quand il peut envoyer des données. Maintenant, normalement lorsque vous appelez write() sur une socket TCP,
TCP effectivement envoyé un segment, mais il n'y a aucune garantie et aucun moyen de force de ce sujet. Il y a beaucoup de raisons pour lesquelles TCP n'envoyer un
segment: une fenêtre fermée et l'algorithme Nagle sont deux choses à
viennent immédiatement à l'esprit.

Lire l'article complet, il est assez en profondeur et clarifié beaucoup de choses pour moi.

Questions connexes