En tant que O.K.W. dit, plusieurs appels BeginSend
en attente fonctionnera bien. Vous avez probablement besoin de garder à l'esprit certaines choses cependant. Tout d'abord, s'il s'agit d'un socket TCP, il s'agit toujours d'un seul flux de données d'égal à égal.
Ensuite, si tous vos appels BeginSend
se produisent sur le même thread alors le résultat sera que le pair reçoit les données dans l'ordre des appels. Si vos appels BeginSend
se produisent à partir de threads différents, les données peuvent arriver dans n'importe quel ordre car il y aura probablement une condition de concurrence entre chacun des envois. Cela peut ou non vous importer (cela dépend si vous envoyez des messages discrets, complets à chaque envoi ou non).Troisièmement, si vous utilisez TCP et envoyez plus rapidement que le code à l'autre extrémité du socket peut recevoir, vous pouvez remplir la fenêtre TCP et les piles TCP va commencer à effectuer le contrôle de flux sur votre flux de données. Si vous continuez à émettre des appels BeginSend
, vous risquez de vous retrouver dans une situation où vos rappels prendront plus de temps à être appelés car la pile TCP sur votre serveur met en file d'attente les données à envoyer (vous recevez uniquement le rappel une fois les données envoyées Le contrôle de flux basé sur la fenêtre TCP empêchera l'envoi de nouvelles données jusqu'à ce que la fenêtre TCP ne soit plus «pleine», c'est-à-dire que le pair a envoyé des ACK pour certaines données in flight
).
Vous pouvez alors entrer dans une situation où vous utilisez des ressources sur l'expéditeur d'une manière incontrôlable (vous émettez un BeginSend
et ne savez pas quand il sera terminé et chaque envoi utilise de la mémoire pour le tampon envoyé et potentiellement non-paged pool
vers le bas dans le code Winsock ... Non-paged pool
est une ressource à l'échelle du système et est assez rare sur les systèmes d'exploitation Vista antérieures et certains pilotes mal comportés peuvent bleu écran la boîte si non-paged pool
est faible ou épuisé. mémoire en mémoire et il y a une autre limite du système sur le nombre de pages mémoire verrouillées
En raison de ces problèmes, il est généralement préférable d'implémenter votre propre flux de niveau de protocole. contrôle qui limite le nombre de BeginSend
appels qui peuvent être en attente à tout moment (en utilisant un ACK de niveau de protocole, peut-être) ou de travailler avec le contrôle de flux TCP Window et utiliser l'achèvement d'un envoi en attente pour émettre un nouvel envoi file d'attente de données à envoyer dans votre propre mémoire et avoir un contrôle complet sur les ressources utilisées et ce que vous faites si vous mettez en file d'attente "trop" de données. Voir mon blog ici pour plus de détails à ce sujet: http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html
Voir cette réponse: what happens when tcp/udp server is publishing faster than client is consuming? pour plus d'informations sur le contrôle de flux TCP Window et ce qui se passe avec E/S chevauchée (en C++ terre) lorsque vous l'ignorez et question trop En résumé, l'envoi simultané de plusieurs appels BeginSend
simultanés est le moyen d'optimiser le flux de données TCP, mais vous devez vous assurer de ne pas envoyer "trop vite" car une fois que vous consommez des ressources dans un manière que vous ne pouvez pas contrôler et qui est potentiellement fatale pour la machine sur laquelle votre code est en cours d'exécution. Donc, ne laissez pas un nombre illimité d'appels BeginSend
être exceptionnels et, idéalement, profilez la boîte pour vous assurer que vous n'épuisez pas les ressources du système.
@Lens, c'est un bon +1 –
@lens: J'ai un fenêtrage intégré dans le protocole que j'envoie (smpp) donc leur envoi ne serait jamais trop rapide. Le point de désordre que vous soulevez serait un problème cependant. – Toad
@Len, mal orthographié votre nom dans mon commentaire ci-dessus, mes excuses :) –