2010-05-11 5 views
24

Nous utilisons .Net et les sockets. Le serveur utilise la méthode Socket.Sender (bytes []) pour envoyer uniquement la charge utile complète. De l'autre côté, nous sommes des clients qui consomment les données. Socket.Receive (tampon []). Dans tous les exemples de Microsoft (et d'autres), ils semblent coller avec une taille de tampon de 8192. Nous avons utilisé cette taille mais de temps en temps nous envoyons des données aux clients qui dépassent cette taille de tampon.Quelle est la taille de la mémoire tampon pour la programmation des sockets?

Existe-t-il un moyen de déterminer combien de données la méthode envoyée par le serveur nous a envoyée? Quelle est la meilleure taille de tampon?

Répondre

31

Même si vous envoyez plus de données que cela, il se peut qu'il ne soit pas disponible dans un appel à recevoir.

Vous ne pouvez pas déterminer la quantité de données que le serveur a envoyé - c'est un flux de données, et vous lisez juste des morceaux à la fois. Vous pouvez lire partie de ce que le serveur a envoyé dans un appel Send, ou vous pouvez lire les données de deux appels Send dans un appel Receive. 8K est une taille de tampon raisonnable - pas si grande que vous perdrez beaucoup de mémoire, et pas si petite que vous aurez à utiliser des tas d'appels de réception gaspillés. 4K ou 16K serait très bien aussi ... Personnellement, je ne commencerais pas à dépasser 16K pour les tampons réseau - je suppose que vous les remplissez rarement.

Vous pouvez expérimenter en essayant d'utiliser un très grand tampon et consigner combien d'octets ont été reçus dans chaque appel - cela vous donnerait une idée de combien est généralement disponible - mais cela ne montrerait pas vraiment l'effet d'utiliser un tampon plus petit. Quelles sont vos préoccupations concernant l'utilisation d'un tampon 8K? Si c'est la performance, avez-vous des preuves que cet aspect de votre code est un goulot d'étranglement?

+0

Je voudrais augmenter la taille de la mémoire tampon si tout est possible. Nous étions en train d'envisager de faire 32K mais je m'inquiétais du scénario ci-dessus où je ne recevrais pas la commande receive même si je l'envoyais en un seul Send. – uriDium

+0

Désolé j'ai oublié de mentionner que nous faisons cela en mode bloquant. Je ne le vois pas faire la différence cependant. – uriDium

+3

@uriDium: Vous devez écrire votre code de manière à ce qu'il ne repose pas sur la réception de tout d'un seul envoi dans une réception. Ce n'est pas le modèle que TCP utilise - c'est un modèle * stream *. Si vous souhaitez segmenter ce flux en messages distincts, vous devez utiliser un délimiteur ou écrire un préfixe de longueur pour chaque message afin que le client sache lire. –

1

8192 serait idéal. Si vous avez des données qui dépassent cette taille, il serait préférable d'envoyer les données dans des paquets de longueur constante.

La taille des données envoyées par le serveur peut être vérifiée à l'aide de la fonction recv dans WINSOCK qui a un paramètre qui donne la longueur de la mémoire tampon.

+0

8192 n'est pas "idéal", mais un nombre généralement utile. Il n'est pas préférable d'envoyer les données dans des paquets de longueur constante: il est préférable de les diffuser le plus rapidement possible. La taille des données envoyées n'a rien à voir avec la valeur retournée par 'recv()' à l'homologue. C'est un protocole de streaming. – EJP

6

Cela dépend de votre protocole. Si vous attendez des messages de plus de 8192 octets, vous devez augmenter la taille de votre tampon en conséquence. Mais gardez à l'esprit que cette taille de tampon est seulement pour un appel à Receive. Si vous voulez vraiment/devez, vous pouvez boucler plusieurs fois Receive et copier les données reçues dans une structure de données arbitrairement grande ou dans un tampon.

Gardez également à l'esprit que c'est une bonne pratique d'appeler Receive à plusieurs reprises jusqu'à ce que vous ayez vérifié que vous avez lu toutes les données pour un message donné; Même si un seul message est inférieur à la taille de votre tampon, il est possible qu'il ne soit pas toujours récupéré par un seul appel Receive.

4

La réponse de Jon Skeet laisse malheureusement une grande partie de l'image - la taille du tampon d'envoi, et le bandwidth-delay product du tuyau que vous écrivez. Si vous essayez d'envoyer des données sur un grand canal à l'aide d'une seule socket et que vous souhaitez que TCP remplisse ce canal, vous devez utiliser une taille de tampon d'envoi équivalente au produit à délai de bande passante du canal. Sinon, TCP ne remplira pas le tuyau car il ne laissera pas assez d'octets en vol à tout moment. Considérons une connexion dont la vitesse est de 1 gigabit et dont la latence unidirectionnelle est de 10 millisecondes en moyenne. Le temps d'aller-retour (aka, la quantité de temps qui s'écoule entre votre socket envoyant un paquet et le temps qu'il reçoit l'accusé de réception pour ce paquet et sait donc envoyer plus de données) est habituellement deux fois la latence.Donc, si vous avez une connexion de 1 gigabit, et un RTT de 20 millisecondes, alors ce tuyau a 1 gigabit/sec * 20 millisecondes == 2,5 mégaoctets de données en vol à tout moment s'il est utilisé complètement. Si votre tampon d'envoi TCP est inférieur à 2,5 mégaoctets, alors ce socket n'utilisera jamais complètement le canal - vous n'obtiendrez jamais un gigabit/s de performance de votre socket. Si votre application utilise de nombreuses sockets, la taille de tous les tampons d'envoi TCP doit être de 2,5 Mo afin d'utiliser pleinement cet hypothétique tube RTT de 1 gigabit/20 ms. Par exemple, si vous utilisez des tampons 8192 octets, vous avez besoin de 30 sockets TCP simultanés pour remplir ce canal.

Questions connexes