使用相同的udp套接字进行异步接收/发送 [英] Use same udp socket for async receive/send
问题描述
我在udp服务器中使用相同的套接字,以便在某些端口上从客户端接收数据,然后在处理请求后使用ip :: ud :: socket :: async_send_to
$ b响应客户端$ b
接收与async_receive_from异步完成。套接字使用相同的ioService(毕竟它是相同的套接字)
文档没有清楚地说明如果一个人可以有一个时刻相同的udp套接字接收来自客户端A的数据报(以异步方式),并可能发送另一个数据报客户端B(异步发送)同时
我怀疑这可能会导致问题。我最后使用相同的套接字作为回复,因为我不能绑定另一个套接字到同一服务器端口,而回复另一个客户端。
如何绑定另一个套接字服务器端口?
编辑。我尝试绑定第二个udp套接字到同一个UDP端口与:
socket(ioService,boost :: asio :: ip :: udp :: endpoint(boost :: asio :: ip :: udp :: v4(),port))
当我第一次这样做(绑定服务器接收套接字)它是确定,但尝试第二次创建另一个套接字,像它报告错误绑定(asio抛出异常)
可以有一个UDP套接字同时从一个远程端点接收并发送到不同的远程端点。但是,根据Boost.Asio Threads and Boost.Asio < a>文档,在单个对象上进行并发调用通常是不安全的。
因此,这是安全的:
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
, / em>,并具有其他线程安全限制。
如果以下任一条件为真,
- 所有套接字调用都在处理程序中发生,
io_service ::
-
async_receive_from
和async_send_to
仅在同一异步操作链中调用。例如,ReadHandler
传递到async_receive_from
调用async_send_to
并且WriteHandler
传递给async_send_to
调用async_receive_from
p>
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的互斥。
必须考虑对象生命周期的管理。如果服务器需要同时处理多个请求,那么请小心每个的 最后, 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 Receive is done async with async_receive_from also. 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. 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: 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) It is possible to have a UDP socket concurrently receiving from one remote endpoint and sending to a different remote endpoint. However, per the Boost.Asio Threads and Boost.Asio documentation, it is generally unsafe to make concurrent calls on a single object. Thus, this is safe: and this is safe: but this is specified as not being safe: Be aware that some functions, such as If either of the following are true, then no additional synchronization needs to occur, as the flow will be implicitly synchronous: 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. 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 Finally, the 这篇关于使用相同的udp套接字进行异步接收/发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!缓冲区
和端点
的所有权> request-> process-> response chain。按 async_receive_from
的文档,调用者保留了缓冲区和端点的所有权。因此,通过 boost :: shared_ptr 可以更容易地管理对象的生命周期。 / a>。否则,如果链足够快,不需要并发链,则它简化了管理,允许每个请求使用相同的缓冲器和端点。
socket_base :: reuse_address
类允许套接字绑定到已在使用的地址。但是,我认为这不是一个适用的解决方案,因为它通常使用:
TIME_WAIT
状态。
socket(ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port))
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
, are a composed operation, and have additional thread safety restrictions.
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 ); --'
}
buffer
and endpoint
for each request->process->response chain. Per async_receive_from
's documentation, the caller retains ownership of both the buffer and endpoint. As such, it may be easier to manage the lifetime of the objects via 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.
socket_base::reuse_address
class allows a socket to be bound to an address that is already in use. However, I do not think it is an applicable solution here, as it is generally used:
TIME_WAIT
state.