(非提升)ASIO `操作中止`错误

(non-boost) ASIO `Operation aborted` error

我正在学习 asio,这是我遇到的错误的最小可重现示例。错误是 Operation aborted(代码 125)。我完全不知道为什么会这样。感谢您的帮助。

#include <asio.hpp>
#include <asio/ip/tcp.hpp>
#include <iostream>
#include <memory>
class connection : public std::enable_shared_from_this<connection>
{
    asio::io_context& context;
    const char* host;
    public:
        connection(const char* host, asio::io_context& context) : context(context), host(host) 
        {}
        
        void start()
        {
            
            auto self = shared_from_this();
            
            asio::ip::tcp::resolver resolver{context};
            resolver.async_resolve(asio::ip::tcp::v4(), host, "http", [self](asio::error_code er, asio::ip::tcp::resolver::results_type endpoint){
                if(!er)
                {   
                  std::cout << endpoint->endpoint().address() << ' ' << endpoint->endpoint().port() << std::endl;
                } else {
                    throw std::runtime_error("Error resolving host: " + er.message() + std::to_string(er.value()));
                }
            });
        }
};
int main()
{
  asio::io_context context;
  std::make_shared<connection>("www.google.com", context)->start();
  context.run();
}

ASIO 的一个基本 属性 是 I/O 对象必须比它们的异步操作长寿。 I/O 个对象的析构函数取消未完成的异步操作。

start()中创建解析器并启动异步解析操作。然后,解析器立即被破坏,从而取消操作。

一个解决方案是让 resolver 成为 connection 的数据成员,这样它就足够长了:

class connection : public std::enable_shared_from_this<connection>
{
    asio::io_context& context;
    const char* host;
    asio::ip::tcp::resolver resolver;

    public:
        connection(const char* host, asio::io_context& context) : context(context), host(host), resolver(context)
        {}
        
        void start()
        {
            auto self = shared_from_this();
            
            resolver.async_resolve(asio::ip::tcp::v4(), host, "http", [self](asio::error_code er, asio::ip::tcp::resolver::results_type endpoint){
                if(!er)
                {   
                  std::cout << endpoint->endpoint().address() << ' ' << endpoint->endpoint().port() << std::endl;
                } else {
                    throw std::runtime_error("Error resolving host: " + er.message() + std::to_string(er.value()));
                }
            });
        }
};

或者,将 resolver 放在它自己的共享指针后面,并在处理程序中捕获共享指针:

class connection : public std::enable_shared_from_this<connection>
{
    asio::io_context& context;
    const char* host;

    public:
        connection(const char* host, asio::io_context& context) : context(context), host(host)
        {}
        
        void start()
        {
            auto self = shared_from_this();

            auto resolver = std::make_shared<asio::ip::tcp::resolver>(context);
            resolver->async_resolve(asio::ip::tcp::v4(), host, "http", [self, resolver](asio::error_code er, asio::ip::tcp::resolver::results_type endpoint){
                if(!er)
                {   
                  std::cout << endpoint->endpoint().address() << ' ' << endpoint->endpoint().port() << std::endl;
                } else {
                    throw std::runtime_error("Error resolving host: " + er.message() + std::to_string(er.value()));
                }
            });
        }
};