C++ 对异步接收/发送使用相同的udp套接字

C++ 对异步接收/发送使用相同的udp套接字,c++,networking,boost,boost-asio,C++,Networking,Boost,Boost Asio,我在udp服务器中使用相同的套接字,以便从某个端口上的客户端接收数据,然后在处理请求后,使用ip::ud::socket::async_send_to对客户端做出响应 接收是异步完成的,异步接收也是从。套接字使用相同的ioService(毕竟是同一个套接字) 文档没有明确说明是否可以让同一个udp套接字接收来自客户端a的数据报(以异步方式),并可能同时向客户端B发送另一个数据报(异步发送) 我怀疑这会导致问题。我最终使用相同的套接字进行应答,因为在应答另一个客户端时,我无法将另一个套接字绑定到同

我在udp服务器中使用相同的套接字,以便从某个端口上的客户端接收数据,然后在处理请求后,使用ip::ud::socket::async_send_to对客户端做出响应

接收是异步完成的,异步接收也是从。套接字使用相同的ioService(毕竟是同一个套接字) 文档没有明确说明是否可以让同一个udp套接字接收来自客户端a的数据报(以异步方式),并可能同时向客户端B发送另一个数据报(异步发送) 我怀疑这会导致问题。我最终使用相同的套接字进行应答,因为在应答另一个客户端时,我无法将另一个套接字绑定到同一个服务器端口

如何将另一个套接字绑定到同一服务器端口

编辑。我尝试使用以下命令将第二个udp套接字绑定到同一udp端口:

socket(ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port))

当我第一次执行此操作时(绑定服务器“接收”套接字),这是正常的,但第二次尝试创建另一个套接字时,它会报告绑定错误(asio抛出异常)

可以让UDP套接字同时从一个远程端点接收数据并发送到另一个远程端点。然而,根据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( ... ); 另一方面,如果有多个线程可能同时调用套接字,则需要进行同步。考虑通过调用函数和处理程序来执行同步,或者使用其他同步机制,如Boo.thTo../P>
除了线程安全外,还必须考虑对象生存期的管理。如果服务器需要同时处理多个请求,那么请注意每个请求->流程->响应链的
缓冲区和
端点的所有权。根据的文档,调用方保留缓冲区和端点的所有权。因此,通过管理对象的生命周期可能更容易。否则,如果链足够快,不需要并发链,那么它可以简化管理,允许每个请求使用相同的缓冲区和端点


最后,该类允许将套接字绑定到已在使用的地址。但是,我不认为这是一个适用的解决方案,因为它通常用于:

  • TCP允许进程重新启动并侦听同一端口,即使该端口处于
    TIME\u WAIT
    状态
  • UDP允许多个进程绑定到同一端口,允许每个进程通过多播接收和广播

请详细说明您的实际问题。您的设置是否正常,您是否正在寻找设计是否正常的确认?或者它不起作用,如果不起作用,你观察到了什么错误?或者您正在询问如何将另一个套接字绑定到服务器端口?@mtrw是否可以将另一个套接字绑定到同一服务器端口?这样我就可以使用不同的套接字发送重播。发生的情况是,我认为我的设置可能导致服务器故障。请编辑您的问题以澄清,而不是添加注释。我假设这里的关键问题是试图将多个套接字绑定到同一端口,这是不可能的,也是毫无意义的。@E_net4确实可以使用UDP,via
SO\u REUSEADDR
:但我同意这是毫无意义的。OP:插座是全双工的,一直到金属:你可以同时读写它们。这是一个令人印象深刻的答案。正如我所说,我的案例中只有一个ioService线程(main),但即使不能调用async\u receive\u from/async\u send\u to,但可以在另一个线程完成之前调用其中一个线程(调用另一个线程的完整处理程序)。这是因为我在另一个与ioService线程无关的线程中这样做。另一件事。其中指定必须以特定方式处理端点类。一旦我在async_receive_中接收到一个端点作为输出参数,我就向它进行复制(使用复制构造函数),并将其作为“状态”传递(以便我知道以后在哪里响应),直到我需要发送响应为止;只是指定对对象的并发调用是不安全的。如果套接字调用是从处理程序外部发生的,并且只有一个线程正在调用
io\u service::run()
,那么将套接字调用发布到
io\u service
将同步。Asio要求调用方保证某些参数在调用处理程序之前保持有效;它从不强迫用户以特定的方式管理它们。在某些情况下,通过智能指针将对象的生命周期与异步链相关联会更容易。asio用户邮件列表中的帖子似乎证实了您的说法。我会将您的答案标记为已接受。我在这里只是想问一下,如果您没有从完成句柄中进行相应的异步调用,您是否会使用此方法中的共享,以防出现错误?您是否保证一旦离开该句柄,就会被删除? thread_1 | thread_2 --------------------------------------+--------------------------------------- socket.async_receive_from( ... ); | socket.async_send_to( ... ); |
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 );  --'
}