I am just learning asio, this is the minimal reproducible example of an error that I have encountered. The error is Operation aborted
(code 125). I have absolutely no idea as to why this happens. Thanks for any help.
#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();
}
A fundamental property of ASIO is that I/O objects must out-live their asynchronous operations. The destructor of I/O objects cancel outstanding asynchronous operaitons.
In start()
, a resolver is created and an asynchronous resolve operation is initiated. Then, immediately, the resolver is destructed, which cancels the operation.
One solution is to make the resolver
a data member of connection
, so that it lives long enough:
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()));
}
});
}
};
Alternatively, put resolver
behind it's own shared pointer and capture the shared pointer in the handler:
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()));
}
});
}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.