DNS Query
O objeto asio::ip::tcp::resolver é usado para resolver nomes de domínio em endereços IP. Ele é útil em situações em que o programa precisa se conectar a um host remoto usando um nome de domínio, mas precisa do endereço IP para estabelecer a conexão de rede.
Para usar o objeto asio::ip::tcp::resolver, inclua o cabeçalho <asio/ip/tcp.hpp> no seu código e crie um objeto da classe passando um asio::io_context para o construtor. Em seguida, use o método resolve para resolver o nome de domínio em um endereço IP.
Resolução Síncrona
O método resolve retorna um range de resultados que pode ser percorrido com range-for moderno:
#include <asio.hpp>
#include <iostream>
int main()
{
try
{
asio::io_context io_context;
asio::ip::tcp::resolver resolver{io_context};
// resolve(host, serviço) — serviço pode ser nome ("https") ou porta ("443")
auto endpoints = resolver.resolve("google.com", "https");
// Iteração moderna com range-for
for (const auto& entry : endpoints)
{
std::cout << entry.endpoint() << '\n';
}
}
catch (std::exception& e)
{
std::cerr << e.what() << '\n';
}
return 0;
}
O resultado da execução será algo como:
142.250.184.206:443
[2800:3f0:4004:811::200e]:443
O tipo asio::ip::tcp::resolver::results_type é um range de basic_resolver_entry:
template <typename InternetProtocol>
class basic_resolver_entry
{
public:
typedef InternetProtocol protocol_type;
typedef typename InternetProtocol::endpoint endpoint_type;
// Conversão implícita para endpoint — permite uso direto com connect()
operator endpoint_type() const { return endpoint_; }
......
}
Como ele possui o operador de conversão endpoint_type(), pode ser passado diretamente para funções como asio::connect():
// O resolver results pode ser passado diretamente para connect
asio::ip::tcp::socket socket{io_context};
asio::connect(socket, endpoints); // itera automaticamente todos os endpoints
Resolução Assíncrona
O método async_resolve resolve o nome de domínio de forma assíncrona, sem bloquear a thread. Isso é essencial em servidores que precisam resolver múltiplos nomes simultaneamente:
#include <asio.hpp>
#include <iostream>
int main()
{
asio::io_context io_context;
asio::ip::tcp::resolver resolver{io_context};
// async_resolve aceita um callback (ou use_awaitable em corrotinas)
resolver.async_resolve("google.com", "https",
[](const asio::error_code& ec,
asio::ip::tcp::resolver::results_type results)
{
if (ec) {
std::cerr << "Erro na resolução: " << ec.message() << '\n';
return;
}
for (const auto& entry : results)
std::cout << entry.endpoint() << '\n';
});
io_context.run(); // processa a operação assíncrona
return 0;
}
Resolução Assíncrona com Corrotinas
Com corrotinas C++20, a resolução assíncrona fica ainda mais legível:
#include <asio.hpp>
#include <asio/co_spawn.hpp>
#include <asio/detached.hpp>
#include <iostream>
using asio::awaitable;
using asio::use_awaitable;
using asio::ip::tcp;
awaitable<void> resolver_dns(asio::io_context& ctx,
const std::string& host)
{
tcp::resolver resolver{ctx};
// co_await suspende a corrotina até a resolução completar
auto endpoints = co_await resolver.async_resolve(host, "https",
use_awaitable);
for (const auto& entry : endpoints)
std::cout << entry.endpoint() << '\n';
}
int main()
{
asio::io_context ctx;
asio::co_spawn(ctx,
resolver_dns(ctx, "google.com"),
asio::detached);
ctx.run();
return 0;
}
Cancelamento
O objeto resolver também permite cancelar uma resolução em andamento com o método cancel():
resolver.cancel(); // cancela todas as operações pendentes no resolver
Isso é útil em aplicações com timeout, onde a resolução não deve bloquear indefinidamente.
Atenção: A classe
resolver::queryfoi depreciada no Asio moderno. Useresolver.resolve(host, serviço)diretamente, sem criar um objetoqueryintermediário.