Was passiert, wenn ich einen Sockel haben, s
, gibt es keine Daten derzeit auf es, es ist ein blockierender Sockel, und ich rufe recv
darauf aus zwei Threads an Einmal? Wird einer der Threads die Daten bekommen? Werden beide es bekommen? Wird der 2. Anruf an recv
mit einem Fehler zurückgeben?Call recv() auf dem gleichen blockierenden Sockel von zwei Threads
Antwort
Ein Thread wird es bekommen, und es gibt keine Möglichkeit zu sagen, welche.
Dies scheint nicht ein vernünftiges Design. Gibt es einen Grund, warum Sie zwei Threads benötigen, die recv()
auf der gleichen Buchse aufrufen?
Socket-Implementierungen sollten Thread-sicher sein, so dass genau ein Thread die Daten erhalten sollte, sobald sie verfügbar sind. Der andere Anruf sollte nur blockieren.
ich eine Referenz für diese nicht finden können, aber hier ist mein Verständnis:
eine Garantie des Herstellers von Thread-Sicherheit ihre eigenen Sockets verwenden jeder sicher, dass mehrere Threads können nur bedeuten kann; Es garantiert nicht Atomizität über einen einzelnen Aufruf, und es verspricht keine bestimmte Zuordnung der Daten des Sockets unter mehreren Threads.
Angenommen, Thread A ruft recv() an einem Socket auf, der TCP-Daten empfängt, die mit hoher Rate übertragen werden. Wenn recv() ein atomarer Aufruf sein muss, kann Thread A alle anderen Threads daran hindern, ausgeführt zu werden, da er fortlaufend ausgeführt werden muss, um alle Daten einzuziehen (bis sein Puffer sowieso voll ist). Das wäre nicht gut. Daher würde ich nicht annehmen, dass recv() immun gegen Kontextwechsel ist.
Umgekehrt, Thread A macht einen Aufruf Aufruf von recv() auf einem TCP-Socket, und die Daten kommen langsam herein. Daher kehrt der Aufruf von recv() mit errno auf EAGAIN zurück.
In beiden Fällen annimmt Thread B recv() auf dem gleichen Socket, während Thread A noch Daten empfängt. Wann hört Thread A auf, Daten an ihn zu übergeben, damit Thread B Daten empfangen kann? Ich kenne keine Unix-Implementierung, die versuchen wird sich zu erinnern, dass Thread A mitten in einer Operation am Socket war; stattdessen ist es Sache der Anwendung (Threads A und B), über ihre Verwendung zu verhandeln.
Im Allgemeinen ist es am besten, die App so zu gestalten, dass nur einer der Threads recv() auf einem einzelnen Socket aufruft.
Ich denke, dass Sie hier mit Ihren Annahmen falsch liegen. recv() ruft ein Datenpaket ab und wird normalerweise mit UDP verwendet, mit TCP erhält es immer noch ein Datenpaket, aber wenn Sie auf der Senderseite nicht sehr vorsichtig waren, können Sie den Inhalt von zwei Schreibvorgängen in einem recv erhalten. –
Okay, ich habe nur die Dokumente überprüft und es ist ein bisschen komplizierter als ein Paket, abhängig von Flags, aber das ist, was ich als den üblichen Fall in Linux-Apps beobachtet habe, an denen ich gearbeitet habe. –
UDP-Datagramme sind sicherlich sicherer als TCP-Streams in Threads. Ich bin mir nicht sicher, ob sie 100% thread-sicher sind - wenn du ein EINTR bekommst (geht das immer noch?), Dann kehrt Thread A vorzeitig von recv() zurück und gibt Thread B die Chance, hineinzuspringen. –
Vom man page auf recv
A recv() auf einem Sockel SOCK_STREAM kehrt so viel verfügbaren Informationen wie die Größe des mitgelieferten Puffer kann halten.
Nehmen wir an, Sie verwenden TCP, da es in der Frage nicht angegeben wurde. Angenommen, Sie haben Thread A und Thread B, die beide auf recv() für Socket s blockieren. Sobald s einige Daten empfangen hat, entsperrt es einen der Threads, sagen wir A, und gibt die Daten zurück. Die zurückgegebenen Daten werden für uns von zufälliger Größe sein. Thread A prüft die empfangenen Daten und entscheidet, ob eine vollständige "Nachricht" vorliegt, wobei es sich bei einer Nachricht um ein Konzept auf Anwendungsebene handelt.
Thread A entscheidet, dass er keine vollständige Nachricht hat, daher ruft er recv() erneut auf.Aber in der Zwischenzeit blockierte B bereits auf der gleichen Buchse und hat den Rest der "Nachricht" erhalten, die für Thread A gedacht war.
Jetzt haben beide Thread A und Thread B eine unvollständige Nachricht und werden, je nachdem, wie der Code geschrieben wird, die Daten als ungültig wegwerfen oder seltsame und subtile Fehler verursachen.
Ich wünschte, ich könnte sagen, dass ich das nicht aus Erfahrung wusste.
Also während recv() selbst technisch Thread sicher ist, ist es eine schlechte Idee, zwei Threads gleichzeitig aufrufen, wenn Sie es für TCP verwenden.
Soweit ich weiß, ist es völlig sicher, wenn Sie UDP verwenden.
Ich hoffe, das hilft.
- 1. senden Recv auf einem Sockel von mehreren Threads
- 2. senden und recv auf Sockel
- 3. Hung-Programm auf einem nicht-blockierenden Sockel
- 4. Sockel C Griff recv() und() zur gleichen Zeit senden
- 5. Zwei Threads arbeiten auf der gleichen Liste
- 6. c - udp senden und empfangen auf dem gleichen Sockel
- 7. Prevent zwei Threads einen Codeblock mit dem gleichen Wert eingeben
- 8. Wie verbinde ich() mit einem nicht blockierenden Sockel?
- 9. Sockel & Zugang zu vielen Klasse mit dem gleichen Namen
- 10. Synchronisation von zwei Threads
- 11. C# mehrere Sockets mit dem gleichen Port auf separaten Threads
- 12. Sockel Leistung auf Linux
- 13. Bereitstellen von zwei verschiedenen Play! Anwendungen auf dem gleichen Hostnamen
- 14. Wie verschiedene Arten von Daten über den gleichen Sockel
- 15. Synchronisieren von zwei Threads
- 16. Sockel Betrieb auf nonsocket
- 17. Sockel Betrieb auf nonsocket
- 18. Mit einem Server zwei Threads zur gleichen Zeit Fortschritte
- 19. Lassen zwei UDP-Server auf dem gleichen Port zuhören?
- 20. Kommunikation zwischen zwei PHP-Anwendungen auf dem gleichen Server?
- 21. Problem mit zwei Direktiven auf dem gleichen Modell
- 22. PHP verschmelzen zwei Arrays auf dem gleichen Schlüssel UND Wert
- 23. Postgres: zwei Wörterbücher mit dem gleichen Namen
- 24. Zwei einfügen Abfrage ... in dem gleichen Klick
- 25. senden TCP-Nachrichten von zwei verschiedenen Threads
- 26. Wie gebe ich ein Zeichen von einer Funktion zurück, die Winsock zum recv vom Sockel verwendet?
- 27. Wie löst man zwei Strukturen mit dem gleichen Namen auf?
- 28. Google Chart - zwei Datums Serie auf dem gleichen Chart
- 29. läuft sphinx in zwei verschiedenen apps auf dem gleichen server
- 30. Plotting zwei y's auf dem gleichen x mit verschiedenen Farben?
Nein, ich implementiere das selbst für ein Projekt und ich wollte wissen, was passieren sollte – Claudiu
Ich fragte, weil ich keinen guten Grund sehe, es so zu gestalten. Einer der Vorteile von Threading besteht darin, Dinge wie Sockets zu isolieren, um die Handhabung zu vereinfachen. Sharing liest auf einem Socket zwischen Threads führt stattdessen viel Komplexität. – dwc
Das Lesen von zwei Threads aus demselben Socket ist sinnvoll, wenn es sich um einen UDP-Socket für ein verbindungsloses Protokoll wie DNS handelt. Jeder Thread arbeitet dann unabhängig von eingehenden Anfragen. – bdonlan