讲师中心 微信公众号
AI工具推荐 视频效率加速

C++如何实现简单的异步 DNS 解析请求器 (A/AAAA 记录)

老枫姑娘_5845

老枫姑娘_5845

发布时间:2026-06-19 06:31:48

|

894人浏览过

|

来源于php中文网

原创

不能直接用 getaddrinfo 做异步 DNS 查询,因为它是阻塞的,会导致线程卡住;即使丢进线程池也属伪异步,无法取消、难集成事件循环、线程开销大。

c++如何实现简单的异步 dns 解析请求器 (a/aaaa 记录)

为什么不能直接用 getaddrinfo 做异步 DNS 查询

因为标准 C++ 没有内置异步 DNS API,而 getaddrinfo 是阻塞的 —— 它会卡住当前线程直到系统 resolver 返回结果(可能几百毫秒甚至超时)。哪怕你把它丢进线程池,也属于“伪异步”:无法取消、无法与 epoll/kqueue 集成、线程开销大,且在高并发场景下容易耗尽线程资源。

用 libuv + uv_getaddrinfo 实现真正异步解析

libuv 是 Node.js 底层跨平台异步 I/O 库,它封装了各系统原生异步 DNS 机制(Linux 上用 getaddrinfo_a 或线程池模拟,macOS/iOS 用 dns_service_create_query,Windows 用 GetAddrInfoEx),对外提供统一回调接口。关键优势是:可取消、无额外线程、能和 TCP/UDP 句柄共用同一个事件循环。

实操要点:

  • uv_getaddrinfo 的 hints.ai_family 设为 AF_UNSPEC 可同时请求 A 和 AAAA;设为 AF_INET 或 AF_INET6 则只查一种
  • 回调函数中必须调用 uv_freeaddrinfo 释放 addrinfo 链表,否则内存泄漏
  • 错误码通过 status 参数返回:UV_EAI_NONAME 表示域名不存在,UV_EAI_FAIL 表示 DNS 服务器拒绝或格式错误,不是网络超时
  • 超时需自行用 uv_timer_t 控制,uv_getaddrinfo 本身不支持 timeout 参数

简短示例(忽略初始化和 loop run):

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
void on_dns_resolve(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
  if (status == 0) {
    for (struct addrinfo* ai = res; ai; ai = ai->ai_next) {
      if (ai->ai_family == AF_INET) {
        char ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &((struct sockaddr_in*)ai->ai_addr)->sin_addr, ip, sizeof(ip));
        printf("A: %s\n", ip);
      } else if (ai->ai_family == AF_INET6) {
        char ip[INET6_ADDRSTRLEN];
        inet_ntop(AF_INET6, &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr, ip, sizeof(ip));
        printf("AAAA: %s\n", ip);
      }
    }
  } else {
    fprintf(stderr, "DNS resolve failed: %s\n", uv_strerror(status));
  }
  uv_freeaddrinfo(res); // 必须调用
  delete req; // req 是 new 出来的,此处释放
}

发起请求:

uv_getaddrinfo_t* req = new uv_getaddrinfo_t;
struct addrinfo hints = {};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int r = uv_getaddrinfo(loop, req, on_dns_resolve, "example.com", nullptr, &hints);
if (r != 0) {
  fprintf(stderr, "uv_getaddrinfo error: %s\n", uv_strerror(r));
  delete req;
}

不用第三方库?std::thread + getaddrinfo 的安全封装要点

若项目禁止引入 libuv 或 Boost.Asio,只能用标准库,那必须自己管理线程+超时+取消。但注意:getaddrinfo 本身不可中断,所以“取消”实际是等待线程自然退出或超时后丢弃结果。

关键约束:

  • 每个查询必须独占一个 std::thread,不能复用线程(getaddrinfo 不是 reentrant 的)
  • 必须用 std::promise/std::future 传递结果,避免裸指针生命周期问题
  • std::thread::joinable() 要检查,防止重复 join 或忘记 join/detach
  • Linux 下建议设置 resolv.conf 中的 options timeout:1 attempts:2,否则默认可能等 5 秒

常见失败场景和调试线索

DNS 异步请求失败,90% 不是代码逻辑问题,而是环境或配置导致:

  • 查不到 AAAA 记录但 A 正常 → 检查本地 DNS 服务器是否支持 IPv6 解析(如 dig AAAA example.com @8.8.8.8)
  • UV_EAI_AGAIN 频繁出现 → 系统 resolver 负载高或 /etc/resolv.conf 配置了 unreachable nameserver
  • 同一域名反复解析变慢 → 检查是否未复用 uv_loop_t,每次新建 loop 会重载 resolver 配置
  • macOS 上返回空结果但无错误 → hints.ai_flags 忘加 AI_ADDRCONFIG,导致 IPv6 接口未启用时 AAAA 查询被静默跳过

真正难处理的是 resolver 层的中间状态:超时、截断、重试策略、EDNS0 支持与否 —— 这些都藏在系统库背后,异步封装层只能暴露结果和粗粒度错误码,细节日志得靠 tcpdump -i any port 53 抓包确认。

热门AI工具

更多
立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2248

2024.03.14

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

1019

2024.03.14

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

427

2024.03.14

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

327

2024.03.14

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

406

2024.03.14

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

580

2024.03.14

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

1409

2024.03.21

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

1217

2024.03.22

Linux 新手先学哪些命令
Linux 新手先学哪些命令

Linux新手命令专题汇集终端基础、文件目录操作、文本查看、软件安装和权限管理等入门文章,帮助按实际任务练习常用命令并建立命令行操作习惯。

0

2026.10.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn