为什么这个使用ASIO async_receive_from的例子没有“漏”

时间:2014-01-02 09:25:16

标签: c++ boost-asio

基本上:

  void start_receive()
  {
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
  {
    if (!error || error == boost::asio::error::message_size)
    {
      boost::shared_ptr<std::string> message(
          new std::string(make_daytime_string()));

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

      start_receive();
    }
  }

自: http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/tutorial/tutdaytime6/src.html

根据我的理解start_recive注册handle_recive,然后调用handle_receive,如果一切正常,则再次调用start_receive重新注册并重复注册。 我不明白是不是数据可能会在调用handle_receive和handle_receive再次调用start_receive之间滑动....

2 个答案:

答案 0 :(得分:2)

技术上可行,但在非饱和条件下udp_server示例不太可能发生。

虽然Boost.Asio可能没有对套接字进行任何挂起的读取操作,但操作系统的网络堆栈会将接收到的数据排入内核内存。当网络堆栈有可用于在给定套接字上读取的数据时,Boost.Asio的异步操作使用反应器来通知。处理完此通知后,Boost.Asio将从套接字启动读取,从而将数据从网络堆栈的内核内存复制到提供的用户内存中。

内核的网络堆栈和套接字通常有一个可配置的参数来控制它们的最大缓冲区大小。例如,receive_buffer_size套接字选项Windows registryLinux sysctl。由于此内存限制和UDP无法保证传送,如果数据报的消耗(读取)速率低于生成(接收)的速率,则网络堆栈可能会丢弃数据报。

答案 1 :(得分:1)

socket_有一个缓冲区,用于存储输入数据直到读取。在示例中udp_server的构造函数中,udp套接字被初始化为侦听端口13。

侦听器服务在main中启动,调用io_service.run()(通常不会返回)。