[英]Use same udp socket for async receive/send
I use the same socket in my udp server in order to receive data from clients on some port, and later after processing of requests respond to to clients using ip::ud::socket ::async_send_to 我在我的udp服务器中使用相同的套接字以便从某些端口上的客户端接收数据,然后在处理请求后使用ip :: ud :: socket :: async_send_to响应客户端
Receive is done async with async_receive_from also. 接收也与async_receive_from异步完成。 The socket uses same ioService (it's the same socket after all) The documentation does not state clearly if one can have at a moment the same udp socket receive datagrams from client A (in async way) and possibly send another datagram to client B (async sent) at the same time I suspect this could lead to problems.
套接字使用相同的ioService(毕竟它是相同的套接字)文档没有明确说明是否可以在同一个udp套接字从客户端A接收数据报(以异步方式)并可能将另一个数据报发送到客户端B(异步)我怀疑这可能导致问题。 I ended up using same socket for reply because I could not bind another socket to the same server port while replying to another client.
我最终使用相同的套接字进行回复,因为在回复另一个客户端时,我无法将另一个套接字绑定到同一个服务器端口。
How can I bind another socket to the same server port? 如何将另一个套接字绑定到同一个服务器端口?
EDIT . 编辑 。 I try to bind the second udp socket to the same UDP port with:
我尝试将第二个udp套接字绑定到同一个UDP端口:
socket(ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port))
When I do this first time (binding for server "receive" socket) it's OK but trying to create another socket the second time like that it reports error at bind (asio throws exception) 当我第一次这样做(绑定服务器“接收”套接字)时没关系,但是第二次尝试创建另一个套接字,就像它在bind上报告错误一样(asio抛出异常)
It is possible to have a UDP socket concurrently receiving from one remote endpoint and sending to a different remote endpoint. 可以从一个远程端点同时接收UDP套接字并发送到不同的远程端点。 However, per the Boost.Asio Threads and Boost.Asio documentation, it is generally unsafe to make concurrent calls on a single object.
但是,根据Boost.Asio Threads和Boost.Asio文档,对单个对象进行并发调用通常是不安全的。
Thus, this is safe: 因此,这是安全的:
thread_1 | thread_2 --------------------------------------+--------------------------------------- socket.async_receive_from( ... ); | socket.async_send_to( ... ); |
and this is safe: 这是安全的:
thread_1 | thread_2 --------------------------------------+--------------------------------------- socket.async_receive_from( ... ); | | socket.async_send_to( ... );
but this is specified as not being safe: 但这被指定为不安全:
thread_1 | thread_2 --------------------------------------+--------------------------------------- socket.async_receive_from( ... ); | socket.async_send_to( ... ); |
Be aware that some functions, such as boost::asio::async_read
, are a composed operation , and have additional thread safety restrictions. 请注意,某些函数(如
boost::asio::async_read
)是一个组合操作 ,并具有其他线程安全限制。
If either of the following are true, then no additional synchronization needs to occur, as the flow will be implicitly synchronous: 如果满足以下任一条件,则不需要进行其他同步,因为流将隐式同步:
io_service::run()
is only invoked from a single thread. io_service::run()
仅在单个线程中调用。 async_receive_from
and async_send_to
are only invoked within the same chain of asynchronous operations. async_receive_from
和async_send_to
仅在同一个异步操作链中调用。 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
. 例如,
ReadHandler
传递给async_receive_from
调用async_send_to
和WriteHandler
传递给async_send_to
调用async_receive_from
。
void read() { socket.async_receive_from( ..., handle_read ); --. } | .-----------------------------------------------' | .----------------------------------------. VV | void handle_read( ... ) | { | socket.async_send_to( ..., handle_write ); --. | } | | .-------------------------------------------' | | | V | void handle_write( ... ) | { | socket.async_receive_from( ..., handle_read ); --' }
On the other hand, if there are multiple threads potentially making concurrent calls to the socket, then synchronization needs to occur. 另一方面,如果有多个线程可能对套接字进行并发调用,则需要进行同步。 Consider performing synchronization by either invoking the functions and handlers through a boost::asio::io_service::strand , or using other synchronization mechanisms, such as Boost.Thread's mutex .
考虑通过boost :: asio :: io_service :: strand调用函数和处理程序,或使用其他同步机制(如Boost.Thread的互斥锁)来执行同步。
In addition to thread safety, the management of object lifetimes must be considered. 除线程安全外,还必须考虑对象生命周期的管理。 If the server needs to process multiple request concurrently, then be careful about ownership of the
buffer
and endpoint
for each request->process->response chain. 如果服务器需要同时处理多个请求,那么请注意每个请求 - >进程 - >响应链的
buffer
和endpoint
所有权。 Per async_receive_from
's documentation, the caller retains ownership of both the buffer and endpoint . 根据
async_receive_from
的文档,调用者保留缓冲区和端点的所有权。 As such, it may be easier to manage the lifetime of the objects via boost::shared_ptr . 因此,通过boost :: shared_ptr管理对象的生命周期可能更容易。 Otherwise, if the chain is quick enough that concurrent chains are not required, then it simplifies management, allowing the same buffer and endpoint to be used per request.
否则,如果链足够快以至于不需要并发链,那么它简化了管理,允许每个请求使用相同的缓冲区和端点 。
Finally, the socket_base::reuse_address
class allows a socket to be bound to an address that is already in use. 最后,
socket_base::reuse_address
类允许将套接字绑定到已在使用的地址。 However, I do not think it is an applicable solution here, as it is generally used: 但是,我不认为这是一个适用的解决方案,因为它通常用于:
TIME_WAIT
state. TIME_WAIT
状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.