可以同时从一个远程端点接收和向另一个远程端点发送UDP套接字。但是,根据Boost.Asio Threads and 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
)是组合操作,并具有额外的线程安全限制。
如果以下任一条件为真,则无需进行额外的同步,因为流程将隐式同步:
- All socket calls occur within handlers, and
io_service::run()
is only invoked from a single thread.
async_receive_from
and async_send_to
are only invoked within the same chain of asynchronous operations. For example, the ReadHandler
passed to async_receive_from
invokes async_send_to
, and the WriteHandler
passed to async_send_to
invokes 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
的文档,调用者保留
buffer和
endpoint的所有权。因此,通过
boost::shared_ptr管理对象的生命周期可能更容易。否则,如果链足够快以至于不需要并发链,则简化了管理,允许在每个请求中使用相同的
buffer和
endpoint。
最后,socket_base::reuse_address
类允许将套接字绑定到已经被占用的地址。然而,我认为这并不是适用的解决方案,因为它通常用于:
- TCP:即使端口处于
TIME_WAIT
状态,允许进程重新启动并监听同一端口。
- UDP:允许多个进程绑定到同一端口,使每个进程能够通过组播接收和广播。
SO_REUSEADDR
来实现,但我同意这是没有意义的。关于套接字(sockets):它们从底层全双工,你可以同时读取和写入它们。 - user207421