web-dev-qa-db-fra.com

Les appels parallèles pour envoyer / recevoir sur la même socket sont-ils valides?

  1. Pouvons-nous appeler send d'un thread et recv d'un autre sur la même socket?
  2. Pouvons-nous appeler plusieurs envois en parallèle à partir de différents threads sur la même socket?

Je sais qu'une bonne conception devrait éviter cela, mais je ne sais pas comment ces API système se comporteront. Je suis incapable de trouver une bonne documentation également pour le même.

Tout pointeur dans la direction sera utile.

115
Jay

POSIX définit l'envoi/recv comme des opérations atomiques, donc en supposant que vous parlez d'envoi/recv POSIX alors oui, vous pouvez les appeler simultanément à partir de plusieurs threads et les choses fonctionneront.

Cela ne signifie pas nécessairement qu'ils seront exécutés en parallèle - dans le cas de plusieurs envois, le second se bloquera probablement jusqu'à la fin du premier. Vous ne le remarquerez probablement pas beaucoup, car un envoi se termine une fois qu'il a placé ses données dans le tampon de socket.

Si vous utilisez des sockets SOCK_STREAM, essayer de faire des choses en parallèle est moins susceptible d'être utile car send/recv peut envoyer ou recevoir seulement une partie d'un message, ce qui signifie que les choses pourraient être divisées.

Le blocage d'envoi/recv sur les sockets SOCK_STREAM ne bloque que jusqu'à ce qu'ils envoient ou recv au moins 1 octet, donc la différence entre le blocage et le non-blocage n'est pas utile.

83
Chris Dodd

Le descripteur de socket appartient au processus, pas à un thread particulier. Par conséquent, il est possible d'envoyer/recevoir vers/depuis le même socket dans différents threads, le système d'exploitation gérera la synchronisation.

Cependant, si l'ordre d'envoi/réception est sémantiquement significatif, vous-même (respectivement votre code) devez assurer un séquencement correct entre les opérations dans les différents threads - comme c'est toujours le cas avec les threads.

16

Je ne vois pas comment recevoir en parallèle pourrait accomplir quoi que ce soit. Si vous avez un message de 3 octets, 1 thread pourrait obtenir les 2 premiers octets et un autre le dernier octet, mais vous n'auriez aucun moyen de savoir lequel était lequel. À moins que vos messages ne durent qu'un octet, il n'y a aucun moyen de faire fonctionner de manière fiable quoi que ce soit avec la réception de plusieurs threads.

Les envois multiples peut-être fonctionnent, si vous avez envoyé le message entier en un seul appel, mais je ne suis pas sûr. Il est possible que l'un en écrase un autre. Il n'y aurait certainement aucun avantage en termes de performances à le faire.

Si plusieurs threads doivent être envoyés, vous devez implémenter une file d'attente de messages synchronisée. Avoir un thread qui effectue l'envoi réel qui lit les messages de la file d'attente et demander aux autres threads de mettre en file d'attente des messages entiers. La même chose fonctionnerait pour la réception, mais le thread de réception devrait connaître le format des messages pour pouvoir les désérialiser correctement.

4
noah