C++ DNS查询程序无法接收Answer记录问题求助
DNS查询程序无法获取Answer记录的问题修复
问题分析
从你提供的DNS响应数据来看,响应头部的RCODE字段为1(格式错误),说明DNS服务器认为你的查询包不符合协议规范,因此返回空的Answer段。核心问题有两点:
- 结构体字节填充导致头部格式错误:
DNSHeader结构体未禁用字节对齐填充,编译器会在成员间或末尾自动添加填充字节,使得发送的头部长度超出标准的12字节,后续的QNAME、QTYPE等字段偏移错误,服务器解析失败。 - QTYPE/QCLASS写入方式不规范:你直接将
htons()转换后的uint16_t值通过push_back()插入,但push_back()仅接受单字节参数,虽然小数值暂时不会出错,但写法存在潜在风险,且可能在特定场景下导致字段值错误。
修复方案
1. 禁用DNSHeader结构体的字节填充
修改DNSHeader定义,添加紧凑打包属性,确保结构体大小严格为12字节:
// 跨平台兼容版本(支持GCC/Clang/MSVC) #pragma pack(push, 1) struct DNSHeader { uint16_t id; // DNS message ID uint16_t flags; // DNS message flags uint16_t qdcount; // Number of entries in the question section uint16_t ancount; // Number of resource records in the answer section uint16_t nscount; // Number of name server resource records in the authority records section uint16_t arcount; // Number of resource records in the additional records section }; #pragma pack(pop) // 仅GCC/Clang也可使用: // struct __attribute__((packed)) DNSHeader { ... };
2. 修正QTYPE和QCLASS的写入逻辑
替换原有的错误写入方式,将16位值拆分为两个字节依次插入:
// 删除原有的QTYPE/QCLASS写入代码,替换为: // 写入QTYPE(已转换为网络字节序) queryPacket.push_back( (question.qtype >> 8) & 0xFF ); queryPacket.push_back( question.qtype & 0xFF ); // 写入QCLASS(已转换为网络字节序) queryPacket.push_back( (question.qclass >> 8) & 0xFF ); queryPacket.push_back( question.qclass & 0xFF ); // 或者更简洁的写法:直接插入整个uint16_t的字节 queryPacket.insert(queryPacket.end(), reinterpret_cast<uint8_t*>(&question.qtype), reinterpret_cast<uint8_t*>(&question.qtype) + 2); queryPacket.insert(queryPacket.end(), reinterpret_cast<uint8_t*>(&question.qclass), reinterpret_cast<uint8_t*>(&question.qclass) + 2);
3. 验证修复效果
修复后重新运行程序,DNS服务器将返回包含Answer段的响应。你可以在receiveAndParseDnsResponse函数中添加解析逻辑,根据头部的ancount值循环读取每个资源记录。
额外建议
- 解析响应时注意处理DNS域名的压缩指针(以
0xC0开头的字节),这是协议中常用的优化方式,避免直接按字符串读取导致解析错误。 - 可以用Wireshark抓包对比你的查询包与
dig命令的查询包,快速定位格式差异。
内容的提问来源于stack exchange,提问作者Marcinnn123
相关产品推荐
相关产品推荐

