141 votes

Les appels parallèles pour envoyer/récupérer sur la même socket sont-ils valides ?

  1. Peut-on appeler send depuis un thread et recv depuis un autre sur la même socket ?
  2. Peut-on 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 exactement comment ces API système vont se comporter. Je ne parviens pas à trouver une bonne documentation à ce sujet.

Toute indication dans ce sens sera utile.

4 votes

Pourquoi prétendez-vous que c'est une mauvaise pratique ? Il me semble que tout va bien parce que vous écoutez et recevez de dans des fils différents.

104voto

Chris Dodd Points 39013

POSIX définit l'envoi et la réception comme des opérations atomiques, donc si vous parlez de l'envoi et de la réception 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 d'envois multiples, le second sera probablement bloqué jusqu'à ce que le premier soit terminé. Vous ne le remarquerez probablement pas, car un envoi se termine une fois que ses données ont été placées dans le tampon de la socket.

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

Les envois/récupérations bloquants sur les sockets SOCK_STREAM ne bloquent que jusqu'à ce qu'ils envoient ou récupèrent au moins 1 octet, donc la différence entre bloquant et non bloquant n'est pas utile.

0 votes

Qu'en est-il du blocage de l'envoi et de la réception ? Sont-ils atomiques ?

0 votes

Cet article ( almaden.ibm.com/cs/people/marksmith/sendmsg.html ) semble confirmer ce que vous dites à propos de SOCK_STREAM mais n'est pas clair à propos de SOCK_DGRAM, d'où proviennent exactement vos informations ?

4 votes

@Joao : Les sockets SOCK_DGRAM sont documentés comme "préservant les limites des messages", ce qui n'est pas très clair. En regardant les sources du noyau linux, vous pouvez au moins voir que chaque envoi et chaque réception traite un seul paquet de manière atomique (au moins pour udp).

24voto

Le descripteur de socket appartient au processus, et non à un thread particulier. Il est donc possible d'envoyer/recevoir vers/depuis la même socket dans différents threads, le système d'exploitation se chargeant de la synchronisation.

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

3voto

noah Points 9333

Je ne vois pas comment la réception en parallèle pourrait servir à quelque chose. Si vous avez un message de 3 octets, un thread pourrait recevoir les 2 premiers octets et un autre le dernier, mais vous n'auriez aucun moyen de savoir lequel est lequel. A moins que vos messages ne fassent qu'un octet de long, il n'y a aucune chance que vous puissiez faire fonctionner quoi que ce soit de manière fiable avec plusieurs threads en réception.

Envois multiples puede Ça pourrait fonctionner, si vous envoyiez le message entier en un seul appel, mais je n'en suis pas sûr. Il est possible que l'un puisse écraser l'autre. Il n'y aurait certainement aucun avantage en termes de performances à le faire.

Si plusieurs threads doivent envoyer des messages, vous devez implémenter une file d'attente de messages synchronisée. Un thread qui effectue l'envoi réel lit les messages de la file d'attente et les autres threads mettent les messages entiers en file d'attente. 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.

10 votes

Si vous utilisez des sockets SOCK_DGRAM, chaque recv recevra un seul datagramme ; il ne sera jamais divisé entre les recvs.

2 votes

@noah, je suis d'accord que les recvs parallèles ne peuvent rien faire. C'est pourquoi je ne l'ai pas demandé. Ma question porte sur l'envoi et la réception en parallèle, puis sur les envois multiples en parallèle. Votre réponse donne un aperçu des envois parallèles. Merci pour cette réponse.

2 votes

@Chris bon point. Je supposais TCP. @Jay Vous pourriez clarifier la question "Peut-on appeler send / recv en parallèle" il semble que vous vouliez recevoir en parallèle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X