Es ist möglich, dass ein UDP-Socket gleichzeitig von einem Remote-Endpunkt empfängt und an einen anderen Remote-Endpunkt sendet. Laut der Boost.Asio-Dokumentation Threads and Boost.Asio ist es jedoch generell unsicher, gleichzeitige Aufrufe für ein einzelnes Objekt durchzuführen.
Somit ist dies sicher:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive_from(...); |
socket.async_send_to(...); |
und das ist sicher:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive_from(...); |
| socket.async_send_to(...);
aber dies ist angegeben als nicht sicher zu sein:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive_from(...); | socket.async_send_to(...);
|
Beachten Sie, dass einige Funktionen wie boost::asio::async_read
, sind eine zusammengesetzte Operation, und haben zusätzliche Thread-Sicherheitsbeschränkungen.
Wenn eine der folgenden Bedingungen erfüllt sind, dann keine zusätzliche Synchronisation muss erfolgen, da die Strömung implizit synchron sein wird:
- Alle Socket-Aufrufe innerhalb Handler auftreten, und
io_service::run()
wird nur aufgerufen, von ein einzelner Thread.
async_receive_from
und async_send_to
werden nur innerhalb derselben Kette asynchroner Operationen aufgerufen. Zum Beispiel ruft der , der an übergeben wurde, async_send_to
auf, und der WriteHandler
, der an async_send_to
übergeben wird, ruft async_receive_from
auf.
void read()
{
socket.async_receive_from(..., handle_read); --.
} |
.-----------------------------------------------'
| .----------------------------------------.
V V |
void handle_read(...) |
{ |
socket.async_send_to(..., handle_write); --. |
} | |
.-------------------------------------------' |
| |
V |
void handle_write(...) |
{ |
socket.async_receive_from(..., handle_read); --'
}
Auf der anderen Seite, wenn es mehrere Threads potentiell machen gleichzeitige Anrufe an die Steckdose, dann muss die Synchronisation auftreten.Ziehen Sie in Betracht, die Synchronisierung auszuführen, indem Sie entweder die Funktionen und Handler über eine boost::asio::io_service::strand aufrufen oder andere Synchronisierungsmechanismen wie Boost.Thread mutex verwenden.
Zusätzlich zur Threadsicherheit muss die Verwaltung der Objektlebensdauern berücksichtigt werden. Wenn der Server mehrere Anforderungen gleichzeitig verarbeiten muss, achten Sie darauf, dass buffer
und endpoint
für jede Anfrage-> Prozess-> Antwort Kette die Eigentümer sind. Gemäß der Dokumentation von async_receive_from
behält der Anrufer sowohl den Puffer als auch den Endpunkt. Daher kann es einfacher sein, die Lebensdauer der Objekte über boost::shared_ptr zu verwalten. Andernfalls, wenn die Kette schnell genug ist, dass keine gleichzeitigen Ketten erforderlich sind, vereinfacht dies die Verwaltung, wobei Puffer und Endpunkt pro Anforderung verwendet werden können.
Schließlich ist die socket_base::reuse_address
Klasse ermöglicht eine Steckdose an eine Adresse gebunden zu sein, die bereits in Gebrauch ist. Aber ich glaube nicht, dass eine anwendbare Lösung ist hier, wie es allgemein verwendet wird:
- Für TCP ein Prozess auf den gleichen Port, auch wenn der Port in einem
TIME_WAIT
Zustand neu zu starten und hören zu können.
- Für UDP, damit mehrere Prozesse an denselben Port gebunden werden können, sodass jeder Prozess Multicast empfangen und übertragen kann.
Bitte geben Sie Ihre aktuelle Frage an. Funktioniert Ihr Setup und Sie suchen nach einer Bestätigung, dass es vom Design her in Ordnung ist? Oder funktioniert es nicht, und wenn nicht, welchen Fehler beobachten Sie? Oder fragen Sie, wie man einen anderen Socket an den Server-Port bindet? – mtrw
@mtrw Ist es möglich, einen anderen Socket an denselben Server-Port zu binden? Auf diese Weise würde ich verschiedene Sockets für das Senden von Wiederholungen verwenden. Was passiert ist, ist, dass ich denke, dass mein Setup eine Fehlfunktion des Servers verursachen kann. – Ghita
Bitte bearbeiten Sie Ihre Frage zu klären, anstatt Kommentare hinzuzufügen –