我在我的udp服务器中使用相同的套接字以便从某些端口上的客户端接收数据,然后在处理请求后使用ip :: ud :: socket :: async_send_to
响应客户端也与async_receive_from完成接收异步。套接字使用相同的ioService(毕竟它是相同的套接字) 文档没有明确说明是否可以在同一时间将相同的udp套接字从客户端A接收数据报(以异步方式)并且可能同时向客户端B发送另一个数据报(异步发送) 我怀疑这可能会导致问题。我最后使用相同的套接字进行回复,因为在回复另一个客户端时,我无法将另一个套接字绑定到同一个服务器端口。
如何将另一个套接字绑定到同一个服务器端口?
修改即可。我尝试将第二个udp套接字绑定到相同的UDP端口:
socket(ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port))
当我第一次执行此操作(绑定服务器“接收”套接字)时,可以尝试再次创建另一个套接字,就像它在bind上报告错误一样(asio抛出异常)
答案 0 :(得分:14)
可以从一个远程端点同时接收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
)是撰写的操作,并且还有其他线程安全限制。
如果满足以下任一条件,则不需要进行其他同步,因为流将隐式同步:
io_service::run()
仅从单个线程调用。 async_receive_from
和async_send_to
仅在同一个异步操作链中调用。例如,传递给ReadHandler
的{{1}}会调用async_receive_from
,传递给async_send_to
的{{1}}会调用WriteHandler
。
async_send_to
另一方面,如果有多个线程可能对套接字进行并发调用,则需要进行同步。考虑通过boost::asio::io_service::strand调用函数和处理程序,或使用其他同步机制(如Boost.Thread的mutex)来执行同步。
除线程安全外,还必须考虑对象生命周期的管理。如果服务器需要同时处理多个请求,请注意每个请求 - >进程 - >响应链的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 ); --'
}
的所有权。根据{{3}}的文档,调用者保留缓冲区和端点的所有权。因此,通过async_receive_from
管理对象的生命周期可能更容易。否则,如果链足够快以至于不需要并发链,那么它可以简化管理,允许每个请求使用相同的缓冲区和端点。
最后,boost::shared_ptr类允许将套接字绑定到已在使用的地址。但是,我不认为这是一个适用的解决方案,因为它通常使用:
buffer
状态。