如何使用yield_context作为resolver.async_resolve的处理程序

How to use yield_context as the handler of resolver.async_resolve?

本文关键字:resolve 处理 程序 async 作为 何使用 yield context resolver      更新时间:2023-10-16

使用yield_context作为堆栈协同程序中异步操作的处理程序真是太棒了!但是ip::basic_resolver::async_resolve的处理程序有一个不同的签名,而不是简单地接收一个错误代码(我很好奇为什么不把resolver::iterator &作为async_resolve的参数,就像basic_socket_acceptor::async_accept中的basic_socket<Protocol1, SocketService> &参数一样)。是否有办法使用yield作为它的处理程序?

这个问题同样适用于async_connect

正如stack - ful Coroutines概述中所述,当将yield_context作为处理程序传递给初始化函数时,其异步操作的处理程序具有如下形式:

void handler(boost::system::error_code ec, result_type result);

初始函数将返回result_type。在本例中,basic_resolver::async_resolve()的处理程序类型要求是ResolverHandler,其形式为:

void resolve_handler(
    const boost::system::error_code& ec,
    boost::asio::ip::tcp::resolver::iterator iterator)

因此,basic_resolver::async_resolve(..., yield_context)将返回resolver::iterator


下面是演示此行为的完整最小示例:

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
int main()
{
  boost::asio::io_service io_service;
  boost::asio::spawn(io_service,
    [&](boost::asio::yield_context yield)
    {
      using tcp = boost::asio::ip::tcp;
      tcp::resolver resolver(io_service);
      // The async_resolve initiating function will return an iterator, as
      // a yield_context is being passed as a handler.
      tcp::resolver::iterator iterator = resolver.async_resolve(
          tcp::resolver::query("www.google.com", "80"), yield);
      // Iterator over endpoints.
      for(tcp::resolver::iterator end; iterator != end; ++iterator)
      {
        std::cout << iterator->endpoint().address().to_string() << std::endl;
      }
    });
  io_service.run();
}
输出:

74.125.227.209
74.125.227.210
74.125.227.211
74.125.227.212
74.125.227.208
2607:f8b0:4000:80a::1012