あるリモートエンドポイントから同時に受信し、別のリモートエンドポイントに送信するUDPソケットを持つことができます。ただし、Boost.AsioスレッドとBoost.Asioのドキュメントによると、単一のオブジェクトで同時呼び出しを行うことは一般的に安全ではありません。
したがって、これは安全です。
thread_1 | thread_2
-------------------------------------- + --------------- ----------------------------
socket.async_receive_from(...); |
socket.async_send_to(...); |
そしてこれは安全です:
thread_1 | thread_2
-------------------------------------- + --------------- ----------------------------
socket.async_receive_from(...); |
| socket.async_send_to(...);
しかし、これは安全ではないと指定されています:
thread_1 | thread_2
-------------------------------------- + --------------- ----------------------------
socket.async_receive_from(...); | socket.async_send_to(...);
|
などの一部の関数は複合操作であり、追加のスレッドセーフ制限があることに注意しboost::asio::async_read
てください。
次のいずれかに該当する場合、フローは暗黙的に同期されるため、追加の同期を行う必要はありません。
- すべてのソケット呼び出しはハンドラー内で発生
io_service::run()
し、単一のスレッドからのみ呼び出されます。
async_receive_from
async_send_to
非同期操作の同じチェーン内でのみ呼び出されます。たとえば、ReadHandler
passed toは、をasync_receive_from
呼び出しasync_send_to
、WriteHandler
passed toは、をasync_send_to
呼び出しますasync_receive_from
。
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 ); --'
}
一方、ソケットを同時に呼び出す可能性のある複数のスレッドがある場合は、同期を行う必要があります。boost :: asio :: io_service :: strandを介して関数とハンドラーを呼び出すか、 Boost.Threadのmutexなどの他の同期メカニズムを使用して、同期を実行することを検討してください。
スレッドセーフに加えて、オブジェクトの存続期間の管理を考慮する必要があります。サーバーが複数の要求を同時に処理する必要がある場合は、各要求->プロセス->応答チェーンの所有権に注意buffer
しendpoint
てください。のドキュメントasync_receive_from
によると、呼び出し元はバッファとエンドポイントの両方の所有権を保持します。そのため、 boost::shared_ptrを使用してオブジェクトの存続期間を管理する方が簡単な場合があります。それ以外の場合、チェーンが十分に高速で並行チェーンが不要な場合は、管理が簡素化され、リクエストごとに同じバッファーとエンドポイントを使用できるようになります。
最後に、このsocket_base::reuse_address
クラスを使用すると、ソケットをすでに使用されているアドレスにバインドできます。ただし、一般的に使用されているため、ここでは適切な解決策ではないと思います。
- ポートが状態にある場合でも、TCPがプロセスを再起動し、同じポートをリッスンできるようにするため
TIME_WAIT
。
- UDPが複数のプロセスを同じポートにバインドできるようにし、各プロセスがマルチキャストを介して受信およびブロードキャストできるようにします。