Question

Que se passe-t-il si j'ai un socket, s s'il n'y a actuellement aucune donnée disponible dessus, qu'il s'agisse d'un socket bloquant et que j'appelle recv dessus à partir de deux threads à la fois? Est-ce que l'un des threads obtiendra les données? Est-ce que les deux vont l'obtenir? Le deuxième appel à <=> renvoyer une erreur?

Était-ce utile?

La solution

Un fil va l'obtenir, et il n'y a aucun moyen de dire lequel.

Cela ne semble pas être une conception raisonnable. Y a-t-il une raison pour laquelle vous avez besoin de deux threads appelant recv() sur le même socket?

Autres conseils

Les implémentations de sockets doivent être sécurisées pour les threads. Par conséquent, un seul thread devrait obtenir les données dès qu'elles sont disponibles. L’autre appel doit simplement bloquer.

Je ne trouve pas de référence pour cela, mais voici ce que j'ai compris:

La garantie de sécurité des threads d'un fournisseur peut signifier que plusieurs threads peuvent utiliser en toute sécurité leurs sockets propres ; il ne garantit pas l'atomicité dans un appel unique et ne promet aucune allocation particulière des données du socket entre plusieurs threads.

Supposons que le fil A appelle recv () sur un socket qui reçoit des données TCP en continu à un débit élevé. Si recv () doit être un appel atomique, le thread A pourrait bloquer l'exécution de tous les autres threads, car il doit fonctionner en permanence pour extraire toutes les données (jusqu'à ce que son tampon soit rempli, de toute façon.) bien. Par conséquent, je ne supposerais pas que recv () soit immunisé contre le changement de contexte.

Inversement, supposons que le thread A effectue un appel bloquant à recv () sur un socket TCP et que les données arrivent lentement. Par conséquent, l'appel à recv () est renvoyé avec errno et mis à EAGAIN.

Dans l'un ou l'autre de ces cas, supposons que le thread B appelle recv () sur le même socket alors que le thread A reçoit toujours des données. Quand le thread A cesse-t-il de recevoir les données afin que le thread B puisse commencer à recevoir des données? Je ne connais pas d'implémentation Unix qui essaiera de se rappeler que le thread A était au milieu d'une opération sur le socket; à la place, il appartient à l’application (threads A et B) d’en négocier l’utilisation.

En général, il est préférable de concevoir l'application de sorte qu'un seul des threads appelle recv () sur un seul socket.

À partir de la page de manuel sur recv

  

Un recv () sur un socket SOCK_STREAM   renvoie autant d'informations disponibles   comme la taille du tampon fourni peut   tenir.

Supposons que vous utilisez TCP, puisqu'il n'a pas été spécifié dans la question. Supposons donc que les threads A et B bloquent tous deux sur recv () pour les sockets. Une fois que s a quelques données à recevoir, il débloquera l'un des threads, disons A et retournera les données. Les données renvoyées auront une taille aléatoire en ce qui nous concerne. Le thread A examine les données reçues et décide si elles ont un & Quot; message & Quot; complet, où un message est un concept de niveau d'application.

Le sujet A décide qu’il n’a pas de message complet. Il appelle à nouveau recv (). MAIS entre-temps, B bloquait déjà sur le même socket et avait reçu le reste du & Message & Quot; qui était destiné au fil A. J'utilise ce que je veux dire ici.

Maintenant, les fils A et B ont un message incomplet et, selon l’écriture du code, rejeteront les données comme étant invalides ou provoqueront des erreurs étranges et subtiles.

J'aimerais pouvoir dire que je ne le savais pas d'expérience.

Ainsi, bien que recv () soit techniquement sûr pour les threads, il est déconseillé d’avoir deux threads l’appelant simultanément si vous l’utilisez pour TCP.

Autant que je sache, l'utilisation du protocole UDP est totalement sûre.

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top