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

Lesezeit: 4 Minuten

Benutzeravatar von Jay
Jay

  1. Können wir send von einem Thread und recv von einem anderen auf demselben 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 mir ist nicht klar, wie sich diese System-APIs verhalten werden. Ich kann auch keine gute Dokumentation dafür finden.

Alle Hinweise in die Richtung sind hilfreich.

  • Warum behaupten Sie, dass dies eine schlechte Praxis ist?. Es sieht für mich gut aus, weil Sie in verschiedenen Threads hören und empfangen.

    – TheMathNoob

    2. September 2017 um 2:22 Uhr

Benutzeravatar von Chris Dodd
Chris Dodd

POSIX definiert send/recv als atomare Operationen. Angenommen, Sie sprechen über POSIX send/recv, dann ja, Sie können sie gleichzeitig von mehreren Threads aufrufen und die Dinge werden funktionieren.

Dies bedeutet nicht unbedingt, dass sie parallel ausgeführt werden – im Falle mehrerer Sendungen wird die zweite wahrscheinlich blockieren, bis die erste abgeschlossen ist. Sie werden wahrscheinlich nicht so viel bemerken, da ein Sendevorgang abgeschlossen ist, sobald er seine Daten in den Socket-Puffer geschrieben hat.

Wenn Sie SOCK_STREAM-Sockets verwenden, ist der Versuch, Dinge parallel zu tun, wahrscheinlich weniger nützlich, 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 Senden/Empfangen auf SOCK_STREAM-Sockets blockiert nur, bis sie mindestens 1 Byte senden oder empfangen, sodass der Unterschied zwischen Blockieren und Nicht-Blockieren nicht sinnvoll ist.

  • @Joao: SOCK_DGRAM-Sockets sind als “Beibehaltung von Nachrichtengrenzen” dokumentiert, was nicht sehr klar ist. Wenn Sie sich die Linux-Kernel-Quellen ansehen, können Sie zumindest sehen, dass jedes Senden und Empfangen ein einzelnes Paket atomar behandelt (zumindest für UDP).

    – Chris Dodd

    16. Mai 2010 um 2:33 Uhr

  • @Kedar: Ich bin mir nicht sicher, was du meinst. EIN send kehrt zurück, sobald die Daten in den Sendepuffer gestellt werden, und die Daten werden asynchron durch den Netzwerkstapel und an das Netzwerk gesendet. Wenn also ein Thread sendet und ein Thread empfängt, ist es durchaus möglich (sogar wahrscheinlich), dass der sendende Thread viele Pakete sendet, bevor der empfangende Thread das erste Paket erhält. Es ist völlig asynchron und nicht simultan.

    – Chris Dodd

    23. Januar 2013 um 17:30 Uhr


  • @ChrisDodd, können Sie einen Link für “POSIX definiert Senden/Empfangen als atomare Operationen” geben?

    – suitianshi

    19. Juli 2016 um 11:02 Uhr

  • @suitianshi: Das POSIX 1003.1c-Standarddokument listet alle Funktionen in 1003.1 auf, die reentrant sind (sicher von Threads aufgerufen werden) und welche nicht. Mir ist leider nirgendwo eine kostenlose Online-Kopie bekannt.

    – Chris Dodd

    19. Juli 2016 um 15:16 Uhr

  • @ChrisDodd Ich habe die Kopie gefunden unix-systems.org/version4 und ich kann die Liste der Systemschnittstellentabelle in Kapitel 7.1 sehen, sehe aber nicht, wo die Funktionen als atomare Operationen aufgeführt sind. Um nicht an Ihnen zu zweifeln, aber können Sie bitte Ihre Antwort teilen/bearbeiten, um Ihren Standpunkt im Dokument zu begründen?

    – Benutzer153882

    5. Juli 2017 um 14:40 Uhr

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

Wenn jedoch die Reihenfolge des Sendens/Empfangens semantisch bedeutsam ist, müssen Sie selbst (bzw. Ihr Code) für die richtige Reihenfolge zwischen den Operationen in den verschiedenen Threads sorgen – wie es bei Threads immer der Fall ist.

Ich sehe nicht, wie ein paralleler Empfang irgendetwas bewirken könnte. 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 welches war. Wenn Ihre Nachrichten nicht nur ein Byte lang sind, gibt es keine Möglichkeit, irgendetwas zuverlässig zum Laufen zu bringen, wenn mehrere Threads empfangen werden.

Mehrere Sendungen könnte funktionieren, wenn Sie die gesamte Nachricht in einem einzigen Anruf senden, aber ich bin mir nicht sicher. Es ist möglich, dass einer einen anderen überschreibt. Es würde sicherlich keinen Leistungsvorteil geben, dies zu tun.

Wenn mehrere Threads senden müssen, sollten Sie eine synchronisierte Nachrichtenwarteschlange implementieren. Haben Sie einen Thread, der das eigentliche Senden durchführt, das Nachrichten aus der Warteschlange liest, und lassen Sie die anderen Threads ganze Nachrichten in die Warteschlange einreihen. Dasselbe würde für den Empfang funktionieren, aber der Empfangsthread müsste das Format der Nachrichten kennen, damit er sie richtig deserialisieren kann.

  • Wenn Sie SOCK_DGRAM-Sockets verwenden, erhält jeder Empfang ein einzelnes Datagramm; es wird niemals zwischen recvs aufgeteilt

    – Chris Dodd

    30. Dezember 2009 um 17:47 Uhr

  • @noah, ich stimme zu, dass parallele Recvs nichts bewirken können. Deshalb habe ich nicht danach gefragt. Meine Frage ist send / recv parallely und dann multiple sends parallely. Ihre Antwort gibt einen Einblick in parallele Sendungen. Danke dafür.

    – Jay

    30. Dezember 2009 um 17:49 Uhr

  • @ Chris guter Punkt. Ich bin von TCP ausgegangen. @Jay Sie könnten die Frage “Können wir send / recv parallely anrufen” so klären, als ob Sie parallel empfangen möchten.

    – Noah

    30. Dezember 2009 um 17:56 Uhr

1423740cookie-checkSind parallele Aufrufe zum Senden/Empfangen auf demselben Socket gültig?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy