gpt4 book ai didi

c++ - 使用相同的 udp 套接字进行异步接收/发送

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:58:06 24 4
gpt4 key购买 nike

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

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

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

编辑。我尝试将第二个 udp 套接字绑定(bind)到同一个 UDP 端口:

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

当我第一次这样做时(绑定(bind)服务器“接收”套接字)没问题,但第二次尝试创建另一个套接字时它会在绑定(bind)时报告错误(asio 抛出异常)

最佳答案

可以让一个 UDP 套接字同时从一个远程端点接收并发送到不同的远程端点。但是,根据 Boost.Asio Threads and Boost.Asio文档,对单个对象进行并发调用通常是不安全的。

因此,这是安全的:

 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.


If either of the following are true, then no additional synchronization needs to occur, as the flow will be implicitly synchronous:

  • 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 .


除了线程安全之外,还必须考虑对象生命周期的管理。如果服务器需要同时处理多个请求,那么请注意每个request->process->responsebufferendpoint 的所有权链。每async_receive_from的文档中,调用者保留对缓冲区端点 的所有权。因此,通过 boost::shared_ptr 管理对象的生命周期可能更容易。 .否则,如果链足够快以至于不需要并发链,那么它会简化管理,允许每个请求使用相同的缓冲区端点


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

  • 对于 TCP,允许进程重新启动并监听同一个端口,即使该端口处于 TIME_WAIT 状态。
  • 对于UDP,允许多个进程绑定(bind)到同一个端口,允许每个进程通过多播接收和广播。

关于c++ - 使用相同的 udp 套接字进行异步接收/发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12252822/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com