关于创建 boost.asio async_xxxx 处理程序对象

Posted

技术标签:

【中文标题】关于创建 boost.asio async_xxxx 处理程序对象【英文标题】:About create boost.asio async_xxxx handler object 【发布时间】:2017-02-04 12:43:44 【问题描述】:

我正在阅读 Boost.Asio 源代码,但其中的代码我很困惑。有没有人帮忙解释一下以便更好地理解,或者我可以参考一些材料来理解?谢谢。

实际代码:

// Wait until data can be received without blocking.
  template <typename Handler>
  void async_receive_from(implementation_type& impl,
      const null_buffers&, endpoint_type& sender_endpoint,
      socket_base::message_flags flags, Handler& handler)
  
    bool is_continuation =
      boost_asio_handler_cont_helpers::is_continuation(handler);

    // Allocate and construct an operation to wrap the handler.
    typedef reactive_null_buffers_op<Handler> op;
    typename op::ptr p =  boost::asio::detail::addressof(handler),
      boost_asio_handler_alloc_helpers::allocate(
        sizeof(op), handler), 0 ;
    p.p = new (p.v) op(handler);

    BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
          &impl, "async_receive_from(null_buffers)"));

    // Reset endpoint since it can be given no sensible value at this time.
    sender_endpoint = endpoint_type();

    start_op(impl,
        (flags & socket_base::message_out_of_band)
          ? reactor::except_op : reactor::read_op,
        p.p, is_continuation, false, false);
    p.v = p.p = 0;
  

特别是:

typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p =  boost::asio::detail::addressof(handler),
  boost_asio_handler_alloc_helpers::allocate(
    sizeof(op), handler), 0 ;
p.p = new (p.v) op(handler);

谢谢。

【问题讨论】:

你能说得更具体些吗——你不明白哪些部分? 你需要一个好的 IDE。 【参考方案1】:

嗯..让我们看看..您正在尝试理解 async_receive_from 类的 async_receive_from 函数。特别是需要null_buffer的那个。

函数的签名:

template <typename Handler>
  void async_receive_from(implementation_type& impl,
                          const null_buffers&, 
                          endpoint_type& sender_endpoint,
                          socket_base::message_flags flags, 
                          Handler& handler)

现在,null_buffers 的重要性是什么?

简而言之,它基本上允许在调用的回调中进行缓冲区管理,而不是在调用async_receive_from 时提供缓冲区,就像在其他重载中一样。 有关其用例的更详细说明,请参阅THIS 答案。

reactive_null_buffers_op&lt;Handler&gt; op 是什么?

既然您已经到了这一点,我假设您知道 asio 中的 operation 类。简而言之,当特定操作完全执行时,它基本上会调用用户提供的回调。在scheduler_operation.hpp 中查找scheduler_operation::complete

reactive_null_buffers_op 派生自scheduler_operation(通过reactive_op),它还存储传递给async_receive_from 的处理程序的副本。实际的细节有点复杂和实用。现在知道这个类的 do_complete 方法是对处理程序的调用就足够了。

typename op::ptr 是什么?

handler_alloc_helpers.hpp 中查找ASIO_DEFINE_HANDLER_PTR。简单来说,它是一个结构,它保存传递给异步函数的处理程序。 ASIO 需要在堆上(或通过自定义分配器)单独分配处理程序,以确保它在套接字接收操作完成期间存在。这就是下面两行的作用:

typename op::ptr p =  boost::asio::detail::addressof(handler),
      boost_asio_handler_alloc_helpers::allocate(
        sizeof(op), handler), 0 ;
    p.p = new (p.v) op(handler);

我们正在通过placement new(第二行)在分配的空间上创建reactive_null_buffers_op&lt;Handler&gt; 的实例。

现在呢?

一个 ASIO 已经存储了用户传递的处理程序对象,它需要在套接字上启动主要的读取操作。为此,它调用start_op 函数。 start_op 的详细信息超出了当前问题的范围。所以,简而言之,start_op 最终将套接字注册到轮询器,比如epoll。而我们的处理程序,现在在op 中,最终会在准备好执行读取操作时被调用(为此跳过了很多细节)。

【讨论】:

我认为这里需要更正:“简而言之,start_op 最终将套接字注册到轮询器”,现在,当您调用 async_* 时调用它的 IO 对象(基本上描述符 ) 必须已经注册,如果没有,它会在启动任何 OP 之前注册,所以 start_op 基本上注册了 Handler;不是套接字(或推送 Handler )到与 IO 对象的描述符数据关联的 op_queue。

以上是关于关于创建 boost.asio async_xxxx 处理程序对象的主要内容,如果未能解决你的问题,请参考以下文章

boost::asio 数据拥有`ConstBufferSequence`

在 Windows 上使用 Boost.Asio 的半并发 ICMP ping

关于 boost::asio::io_context::run 的困惑

Simple Boost::Asio 异步 UDP 回显服务器

我们可以用 boost.asio 创建未命名的套接字来模拟匿名管道吗?

boost.asio 和文件 i/o 有啥关系?