关于创建 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<Handler> 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<Handler>
的实例。
现在呢?
一个 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 回显服务器