DNS¶
Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.
功能概述¶
DNS(Domain Name System,域名系统)是一种基于UDP协议的域名解析工具,用于将域名转换为IP地址。其原理是:发送 DNS 查询请求,等待服务器返回 IP 地址信息。
在嵌入式/物联网场景中,DNS常见用途:
网络连接初始化
域名解析以访问远程服务器
故障定位(检查DNS服务器可用性)
模块支持异步和同步解析模式,支持IPv4/IPv6双栈,适用于资源受限的嵌入式设备。遵循RFC 1035标准,确保兼容性。
基本要素¶
工作原理:客户端发送UDP查询包到DNS服务器,服务器返回包含IP地址的响应包。支持递归/迭代查询。
网络协议支持:基于UDP(端口53),可选TCP用于大响应。
输入信息:
域名(hostname):如"www.example.com",最大256字符。
地址类型(hints):指定IPv4 (AF_INET) 或 IPv6 (AF_INET6)。
输出信息:
IP地址链表:qosa_addrinfo_s 结构体,包含 ip_addr 和 ai_family。
常见结果:
成功:返回IP地址链表。
失败:如域名不存在、超时或内存不足。
故障排查步骤:
检查网络连接(Ping DNS服务器,如8.8.8.8)。
验证域名格式。
测试IPv4/IPv6分别解析。
流程概述¶
DNS操作流程主要包括以下步骤:
初始化参数:设置SIM/PDP ID、域名、hints(地址类型)。
等待网络就绪(PDP激活)。
发送查询:异步(qosa_dns_asyn_getaddrinfo())或同步(qosa_dns_syn_getaddrinfo())。
处理响应:解析IP地址链表。
释放资源:调用 qosa_dns_result_free()。
消息结构¶
DNS消息基于UDP,使用端口53。标准DNS消息包括头部(12字节)、问题区、回答区、授权区和附加区。根据RFC 1035,消息格式如下。
以下是DNS消息结构图:
偏移量细节(字节为单位):
0~1:ID
2~3:Flags (QR、Opcode、AA、TC、RD、RA、Z、RCODE)
4~5:QDCOUNT
6~7:ANCOUNT
8~9:NSCOUNT
10~11:ARCOUNT
12+:Question/Answer等(可变)。
备注
域名使用压缩指针避免重复;QTYPE:1 = A (IPv4), 28 = AAAA (IPv6)。
API说明¶
头文件¶
qosa_asyn_dns.h
函数概览¶
函数 |
描述 |
|---|---|
qosa_dns_asyn_getaddrinfo() |
异步DNS解析域名 |
qosa_dns_syn_getaddrinfo() |
同步DNS解析域名 |
qosa_dns_result_free() |
释放DNS解析结果 |
qosa_dns_asyn_getaddrinfo¶
功能描述
异步DNS解析接口,用于解析域名到IP地址,支持IPv4或IPv6,并通过回调函数通知结果。该函数适用于需要非阻塞操作的场景,如多任务环境,避免阻塞主线程。函数原型
qosa_dns_error_e qosa_dns_asyn_getaddrinfo(qosa_uint8_t simcid,
qosa_uint8_t pdpcid,
const char *hostname,
struct qosa_addrinfo_s *hints,
dns_result_callback cb,
void *user_argv);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
simcid |
输入 |
qosa_uint8_t |
SIM ID |
pdpcid |
输入 |
qosa_uint8_t |
PDP ID |
hostname |
输入 |
const char* |
要解析的域名信息,长度不超过 QOSA_DNS_REQUEST_MAX_LEN (256 字符) |
hints |
输入 |
struct qosa_addrinfo_s* |
主要用于指定解析的地址类型(如IPv4或IPv6);详见 qosa_addrinfo_s |
cb |
输入 |
dns_result_callback |
用户注册的异步通知回调函数,在回调函数中禁止进行自己的数据业务,可能导致数据临界问题 |
user_argv |
输入 |
void* |
用户自定义参数指针 |
返回值说明
QOSA_DNS_RESULT_OK:函数执行成功
其他值:函数执行失败;详见 qosa_dns_error_e
备注
如果DNS请求成功,调用者需要在回调函数中调用 qosa_dns_result_free() 函数释放地址指针。
回调函数中禁止进行阻塞操作或复杂业务逻辑,以避免影响系统性能。
hostname 长度超过256字符将导致解析失败,返回 QOSA_DNS_RESULT_ERROR。
hints 参数用于指定 ai_family(如AF_INET for IPv4, AF_INET6 for IPv6),其他成员可设为0。
该函数异步执行,不会阻塞调用线程,结果通过 cb 回调返回。
如果内存分配失败,返回 QOSA_DNS_MEMORY_ERROR。
qosa_dns_syn_getaddrinfo¶
功能描述
同步DNS解析接口,用于解析域名到IP地址,支持IPv4或IPv6,直接返回结果。该函数适用于简单场景,需要阻塞等待解析完成。函数原型
qosa_dns_error_e qosa_dns_syn_getaddrinfo(qosa_uint8_t simcid,
qosa_uint8_t pdpcid,
const char *hostname,
struct qosa_addrinfo_s *hints,
struct qosa_addrinfo_s **res);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
simcid |
输入 |
qosa_uint8_t |
SIM ID |
pdpcid |
输入 |
qosa_uint8_t |
PDP ID |
hostname |
输入 |
const char* |
要解析的域名信息,长度不超过 QOSA_DNS_REQUEST_MAX_LEN (256 字符) |
hints |
输入 |
struct qosa_addrinfo_s* |
主要用于指定解析的地址类型(如IPv4或IPv6);详见 qosa_addrinfo_s |
res |
输入 |
struct qosa_addrinfo_s** |
解析结果输出,如果失败则 *res = NULL;详见 qosa_addrinfo_s |
返回值说明
QOSA_DNS_RESULT_OK:函数执行成功
其他值:函数执行失败;详见 qosa_dns_error_e
备注
如果DNS请求成功,调用者需要调用 qosa_dns_result_free() 函数释放 res 指向的内存。
该函数是同步的,会阻塞调用线程直到解析完成或超时,可能影响实时性。
hostname 长度超过256字符将导致解析失败,返回 QOSA_DNS_RESULT_ERROR。
hints 参数用于指定 ai_family(如AF_INET for IPv4, AF_INET6 for IPv6),其他成员可设为0。
如果内存分配失败,返回 QOSA_DNS_MEMORY_ERROR。
qosa_dns_result_free¶
功能描述
释放DNS返回结果内存,适用于异步或同步解析成功后的结果释放。函数原型
void qosa_dns_result_free(struct qosa_addrinfo_s *info);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
info |
输入 |
struct qosa_addrinfo_s* |
要释放的 qosa_addrinfo_s 结构体;详见 qosa_addrinfo_s |
返回值说明
无
备注
必须在DNS解析成功后调用此函数释放内存,以避免内存泄漏。
如果 info 为NULL,则无操作,不引发错误。
链表结构中会递归释放所有 ai_next 节点。
结构体定义¶
qosa_addrinfo_s¶
struct qosa_addrinfo_s
{
int ai_family;
char ip_addr[CONFIG_QOSA_INET6_ADDRSTRLEN];
struct qosa_addrinfo_s *ai_next;
};
参数 |
类型 |
说明 |
|---|---|---|
ai_family |
int |
IP地址类型(如AF_INET或AF_INET6) |
ip_addr |
char |
字符类型IP地址,如"127.0.0.1"或IPv6地址,最大48字符 |
ai_next |
struct qosa_addrinfo_s |
存储地址的下一个节点(链表结构);详见 qosa_addrinfo_s |
枚举定义¶
qosa_dns_error_e¶
typedef enum
{
QOSA_DNS_RESULT_OK = 0,
QOSA_DNS_RESULT_ERROR = 1 | QOSA_ERRCODE_DNS_BASE,
QOSA_DNS_MEMORY_ERROR = 2,
QOSA_DNS_RESULT_MAX
} qosa_dns_error_e;
成员 |
说明 |
|---|---|
QOSA_DNS_RESULT_OK |
DNS请求成功 |
QOSA_DNS_RESULT_ERROR |
DNS请求失败 |
QOSA_DNS_MEMORY_ERROR |
DNS内部内存分配失败 |
QOSA_DNS_RESULT_MAX |
最大枚举值 |
应用逻辑流程图¶
示例代码¶
完整示例代码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/network/network_protocol/dns/dns_demo.c 。
功能配置建议¶
DNS配置主要通过hints结构体指定解析类型。以下是详细建议,适用于嵌入式场景。
simcid(SIM卡ID)
推荐:0(主SIM)。
解释:选择稳定SIM;在双SIM设备中动态检测信号。
pdpcid(PDP ID)
推荐:1(默认上下文)。
解释:确保PDP激活前调用。
hostname(域名)
推荐:有效域名,如"www.baidu.com",< 256字符。
解释:避免无效域名导致
QOSA_DNS_RESULT_ERROR。
hints.ai_family(地址类型)
推荐:AF_INET (IPv4) 或 AF_INET6 (IPv6)。
解释:默认IPv4;IPv6需网络支持。其他成员设为0。
通用指南:异步模式优先(非阻塞);释放内存避免泄漏。示例中 hints.ai_family = AF_INET。
常见问题排查指南¶
问题现象(错误码) |
可能原因 |
建议解决方案 |
|---|---|---|
QOSA_DNS_RESULT_ERROR |
域名无效、超时或网络问题 |
检查 hostname;测试网络(Ping DNS服务器);增大超时。 |
QOSA_DNS_MEMORY_ERROR |
内存不足 |
优化代码;增加栈大小;检查系统负载。 |
回调未触发(异步) |
任务/队列初始化失败 |
检查异步回调是否已正确注册;确认网络已就绪且调用线程未阻塞结果处理流程;如使用异步解析,请确保应用层事件循环能够正常接收并处理回调通知。 |
res = NULL(同步) |
解析失败 |
验证 hints;使用IP代替域名测试。 |
内存泄漏 |
未调用 qosa_dns_result_free() |
在成功后释放 info。 |
附录¶
术语缩写表¶
缩写 |
全称 |
说明 |
|---|---|---|
DNS |
Domain Name System |
域名系统,用于地址解析 |
UDP |
User Datagram Protocol |
用户数据报协议,DNS传输层 |
IP |
Internet Protocol |
互联网协议 |
IPv4 |
Internet Protocol version 4 |
互联网协议第4版 |
IPv6 |
Internet Protocol version 6 |
互联网协议第6版 |
PDP |
Packet Data Protocol |
分组数据协议,用于移动网络 |
SIM |
Subscriber Identity Module |
用户身份模块(SIM卡) |