c++ - boost .Asio : The I/O operation has been aborted because of either a thread exit or an application request

标签 c++ boost boost-asio asio

我正在学习 Boost.Asio。我创建了一个简单的程序来将主机名解析为 IP 地址。使用同步解析操作时它工作正常。但是,当我尝试异步方式时,出现了一些奇怪的行为。

#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

using boost::asio::ip::tcp;

void resolver_handler(
    const boost::system::error_code& err,
    tcp::resolver::iterator it
) {
    if (err) {
        std::cerr << "Resolver error: " << err.message() << std::endl;
        return;
    }
    tcp::resolver::iterator end;
    while (it != end) {
        std::cout << "Host name: " << it->host_name() << std::endl;
        std::cout << "Endpoint: " << it->endpoint() << std::endl;
        std::cout << "Service name: " << it->service_name() << std::endl;
        ++it;
    }
}

void resolve_host(boost::asio::io_service& io_service) {
    tcp::resolver::query query("www.google.com", "http");
    tcp::resolver resolver(io_service);
    resolver.async_resolve(
        query,
        boost::bind(
            resolver_handler,
            boost::asio::placeholders::error,
            boost::asio::placeholders::iterator
        )
    );
    std::cout << "Bind" << std::endl;  // <<<----This line
}

int main(int argc, char **argv) {
    try {
        boost::asio::io_service io_service;
        resolve_host(io_service);
        io_service.run();
    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
}

resolve_host函数的最后一行被注释掉时,报告

Resolver error: The I/O operation has been aborted because of either a thread exit or an application request

当该行出现时,它会给出正确的输出

Bind
Host name: www.google.com
Endpoint: 216.58.219.4:80
Service name: http

我所做的是打印出一些东西。我试图在 async_resolve 调用之后添加一些更简单的逻辑(例如 int a = 1;),但它不起作用。在我看来,这是一个时间问题。也许某些东西退出得太快了。

我搜索此错误消息,但发现大多数帖子都是关于 C# 的。我相信这个错误消息不是来自 Boost,而是来自 Windows 系统。

谁能给我解释一下为什么会这样?非常感谢。

最佳答案

正如@David Schwartz 所说,您必须让解析器保持事件状态才能完成异步操作。

这是我能想到的最简单的方法:

void resolve_host(boost::asio::io_service& io_service) {
    tcp::resolver::query query("www.google.com", "http");
    auto resolver = std::make_shared<tcp::resolver>(io_service);
    resolver->async_resolve(
        query,
        [resolver](auto ec, auto it) { resolver_handler(ec, it); }
    );
}

请注意,我使用了 lambda 来捕获解析器(它是动态分配的,而不是在堆栈上分配的)。

如果您没有该选项,最简单的方法是将一些不透明的上下文绑定(bind)到完成处理程序 bind:

using opaque_context = std::shared_ptr<void const>;

void resolver_handler(
    const boost::system::error_code& err,
    tcp::resolver::iterator it,
    opaque_context
) {
    // ...

然后使用

resolver->async_resolve(
    query,
    boost::bind(resolver_handler, ph::error, ph::iterator, resolver)
);

参见在 Coliru 上编译:c++03 only , C++11 opaque_context , c++11 lambda

请注意,我可能会传递 endpoint 而不是 iterator 以进一步解耦代码(参见例如 ASIO getting a tcp endpoint directly from an asynchronous resolve )。但您不需要这样做,因为迭代器 确实 使关联状态保持事件状态:What's the lifetime of boost::asio::ip::tcp::resolver::iterator from async_resolve?

关于c++ - boost .Asio : The I/O operation has been aborted because of either a thread exit or an application request,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47254109/

相关文章:

c++ - 如何在一台机器上构建 vc9 和 vc10 版本的 Boost?

c++ - 使用 Boost::iostreams 两用过滤器

android - boost 信号 : Connect fails

c++ - Boost::Asio 同步客户端超时

c++ - 在 C++ 中检查哈希的大小

c++ - 关于编写具有相同指针数组的类的代码中的错误?

c++ - 异步读取服务器 BoostAsio 不调用处理程序

c++ - io_service::post 函数内的 boost::bind 组合

c++ - std::unordered_map 是如何存储和比较其键值以实现无序快速访问元素的?

c++ - 尝试将 Boost 与 CMake 链接时遇到 LNK2019 错误