webentwicklung-frage-antwort-db.com.de

Sind parallele Anrufe zum Senden / Empfangen auf demselben Socket gültig?

  1. Können wir send von einem Thread und recv von einem anderen am selben Socket aufrufen?
  2. Können wir mehrere Sends parallel von verschiedenen Threads auf demselben Socket aufrufen?

Ich weiß, dass ein gutes Design dies vermeiden sollte, aber ich bin nicht sicher, wie sich diese System-APIs verhalten werden. Ich bin nicht in der Lage, eine gute Dokumentation zu finden.

Alle Hinweise in die Richtung werden hilfreich sein.

115
Jay

POSIX definiert send/recv als atomare Operationen. Wenn Sie also von POSIX send/recv sprechen, können Sie sie von mehreren Threads gleichzeitig aufrufen, und es wird funktionieren.

Dies bedeutet nicht unbedingt, dass sie parallel ausgeführt werden. Bei mehreren Sends wird der zweite wahrscheinlich blockiert, bis der erste abgeschlossen ist. Sie werden wahrscheinlich nicht so viel bemerken, da ein Sendevorgang abgeschlossen ist, sobald seine Daten in den Socket-Puffer gestellt wurden.

Wenn Sie SOCK_STREAM-Sockets verwenden, ist es weniger wahrscheinlich, dass Sie versuchen, Dinge parallel auszuführen, da send/recv möglicherweise nur einen Teil einer Nachricht sendet oder empfängt, was bedeutet, dass die Dinge aufgeteilt werden könnten.

Das Blockieren von send/recv auf SOCK_STREAM-Sockets blockiert nur, bis sie mindestens 1 Byte senden oder empfangen, sodass der Unterschied zwischen blockierend und nicht blockierend nicht sinnvoll ist.

83
Chris Dodd

Der Socket-Deskriptor gehört zum Prozess und nicht zu einem bestimmten Thread. Daher ist es möglich, in verschiedenen Threads an denselben Socket zu senden/von demselben Socket zu empfangen. Das Betriebssystem übernimmt die Synchronisierung.

Wenn die Reihenfolge des Sendens/Empfangens jedoch von semantischer Bedeutung ist, müssen Sie selbst (bzw. Ihr Code) die richtige Reihenfolge zwischen den Vorgängen in den verschiedenen Threads sicherstellen - wie dies bei Threads immer der Fall ist.

16

Ich sehe nicht, wie das parallele Empfangen irgendetwas bewirken kann. Wenn Sie eine 3-Byte-Nachricht haben, könnte 1 Thread die ersten 2 Bytes und ein anderer das letzte Byte erhalten, aber Sie hätten keine Möglichkeit zu sagen, welches was war. Solange Ihre Nachrichten nicht nur ein Byte lang sind, können Sie mit dem Empfang mehrerer Threads nichts zuverlässig zum Laufen bringen.

Mehrere Sends könnten funktionieren, wenn Sie die gesamte Nachricht in einem einzigen Anruf gesendet haben, aber ich bin mir nicht sicher. Es ist möglich, dass einer einen anderen überschreibt. Dies hätte sicherlich keinen Leistungsvorteil.

Wenn mehrere Threads gesendet werden müssen, sollten Sie eine synchronisierte Nachrichtenwarteschlange implementieren. Haben Sie einen Thread, der das eigentliche Senden von Nachrichten aus der Warteschlange liest, und haben Sie die anderen Threads, die ganze Nachrichten in die Warteschlange stellen. Das Gleiche würde für den Empfang funktionieren, aber der Empfangsthread müsste das Format der Nachrichten kennen, damit er sie ordnungsgemäß deserialisieren kann.

4
noah