2011-10-14 2 views
3

J'ai fait mes recherches et je sais que la meilleure façon de mettre en œuvre un serveur socket haute performance est généralement la suivante: utiliser des opérations de socket async (SocketAsyncEventArgs/Operations pour des performances optimales) et le rappel asynchrone, placez la requête dans une file d'attente de traitement traitée par un pool de threads.Serveur Socket Super Haute Performance - Détails de l'implémentation

Mes questions pour ce modèle de traitement - d'avoir les meilleures performances:

1) lorsque l'opération doit « fin » de la prise appelée (par exemple EndAccept ou EndReceive)? devrait-il être appelé sur le thread de rappel (IOCP) avant de mettre en file d'attente la demande? ou appelé lorsque la demande est retirée de la file d'attente et est traitée (thread de travail)?

2) cette question dépend de la réponse à # 1. quand doit-on appeler la prochaine opération "Begin"? Devrions-nous l'appeler avant que nous appelons EndOperation même ou devrions-nous l'appeler immédiatement après EndOperation (avant la demande de mise en file d'attente/de traitement)? 3) la file d'attente de traitement peut-elle simplement être le pool d'unités d'exécution .NET? Quels sont les avantages/inconvénients de l'utilisation du pool de threads .NET par rapport au déploiement de votre propre file d'attente de traitement synchronisée?

Toute aide est grandement appréciée.

+1

Vous n'avez pas bien fait vos recherches: SocketAsyncEventArgs et Begin/End sont deux modèles différents. Vous n'appelez pas par ex. EndReceive lorsque vous avez appelé ReceiveAsync. – dtb

+0

En ce qui concerne # 1, les opérations 'EndXXX' devraient être appelées à l'intérieur du callback et à l'extérieur aussi (si la requête s'est terminée de manière synchrone). C'est un peu difficile de bien faire les choses. Voir ce [post] (http: //blogs.msdn.com/b/mjm/archive/2005/05/04/414793.aspx) pour une explication. Si vous voulez éviter cela et utiliser une solution plus élégante, je vous suggère d'aller avec TPL et son 'FromAsync'. –

+1

@dtb vous avez raison, le modèle est légèrement différent, mais les deux modèles suivent le concept global de traitement asynchrone via les callbacks et mes questions sont toujours pertinentes pour les deux – shyneman

Répondre

2

1) Le EndReceive devrait être la première chose que vous faites dans le rappel asynchrone. En fait, vous ne pouvez rien faire d'autre dans le rappel tant que vous n'avez pas appelé EndReceive, car c'est ce qui vous donne les données reçues. Voir l'exemple au Socket.EndReceive.

Même chose pour EndAccept, car il vous donne le socket avec lequel vous communiquerez.

2) Vous devez appeler le BeginAccept dès que possible après le EndAccept. Dans le cas contraire, vous risquez de manquer des demandes de connexion si votre callback est trop long à traiter. Bien sûr, si votre callback prend du temps à faire quoi que ce soit, vous le faites mal. Encore une fois, la même chose vaut pour BeginReceive: appelez-le dès que possible après EndRead, pour éviter de perdre des données. Ou, si votre protocole de communication est un modèle de demande/réponse, où le client attend une réponse avant d'envoyer d'autres données, vous pouvez attendre d'appeler BeginRead jusqu'à ce que vous ayez envoyé la réponse.

3) Le traitement pourrait être le pool de threads .NET, bien que si vous allez l'utiliser, vous devriez utiliser la bibliothèque parallèle de tâches. L'avantage de l'utilisation de la NPT est qu'elle «brûle et oublie», ou peut-être «tire et rappellera quand elle sera terminée». L'inconvénient de l'utilisation du TPL est qu'il est plus difficile pour votre application de savoir quelles tâches sont en attente. Si vous créez votre propre file d'attente de traitement synchronisée, vous savez toujours quels travaux sont en attente et vous avez la possibilité d'examiner la file d'attente, d'annuler des tâches, etc. Si vous voulez le faire avec le TPL, vous créez une collection de tâches vous devez gérer, car il y a no way to get the the list of pending tasks. Mais si vous n'avez pas besoin de voir les tâches en attente, alors TPL devrait fonctionner correctement.

Les questions connexes ici ont de bonnes informations.

+0

Concernant le # 1, je voudrais ajouter que le modèle APM standard est un peu plus compliqué que ça. Parce qu'il est possible que la pile déborde dans des implémentations naïves. Pour un, les méthodes 'EndXXX' devraient également être appelées en dehors du rappel si la requête est terminée de manière synchrone. Voici un [blog] (http://blogs.msdn.com/b/mjm/archive/2005/05/04/414793.aspx) à ce sujet. Ceci est pris en compte si l'on utilise TPL. –

+0

Pour # 1: si vous mettez en file d'attente tout le processus asyncresult sans appeler Endxxx, ne pouvez-vous pas libérer le thread IOCP plus tôt? Pour # 2, je pense que nous pouvons convenir qu'il devrait l'appeler dès que possible afin que vous puissiez traiter la prochaine connexion dans le tampon d'acceptation. Pour le numéro 3, je jetterai un coup d'oeil sur TPL ... grâce à tout ce qui l'a suggéré. – shyneman

+0

@IlianPinzon Alors, dites-vous que la méthode Endxxx doit être appelée à l'intérieur du thread de travail de traitement PAS le thread IOCP de socket? Et merci d'avoir suggéré TPL. – shyneman

Questions connexes