【C/C++】用 C 语言手写 DNS 查询:理解 UDP 和协议报文

【C/C++】用 C 语言手写 DNS 查询:理解 UDP 和协议报文 目录用 C 语言手写 DNS 查询理解 UDP 和协议报文用 C 语言手写 DNS 查询理解 UDP 和协议报文学习代码dns/dns.cDNS 项目让我第一次比较具体地感受到网络编程不只是socket、sendto、recvfrom更重要的是理解协议格式。UDP 本身只负责把一段数据发给对方至于这段数据里每个字节是什么意思要由应用层协议决定。DNS 查询就是一个很好的练习因为它的头部固定问题区可变既有结构又不会过分复杂。项目里定义了 DNS 头部structdns_header{uint16_tid;uint16_tflags;uint16_tquestions;uint16_tanswer;uint16_tauthority;uint16_tadditional;};这 12 个字节里id用来匹配请求和响应flags表示查询标志questions表示问题数量。写 DNS 请求时不能只把结构体随便发出去还要注意网络字节序。多字节字段在网络上传输通常使用大端序因此构造报文时需要htons()之类的转换。DNS 问题区最有意思的是域名编码。普通字符串是www.baidu.com但 DNS 报文里不是直接这样放而是按“长度 内容”的形式编码3www5baidu3com0也就是说每一段标签前面放一个长度字节最后用0结束。这个格式一开始不直观但它让解析方不需要扫描点号只要读长度就知道下一段有多长。UDP 部分的流程相对直接sockfdsocket(AF_INET,SOCK_DGRAM,0);sendto(sockfd,request,request_len,0,(structsockaddr*)server_addr,sizeof(server_addr));recvfrom(sockfd,response,sizeof(response),0,NULL,NULL);我的理解是UDP 的“简单”并不等于应用简单。它没有 TCP 的连接管理和可靠传输所以速度快、开销低适合 DNS 这种一次请求一次响应的场景。但也正因为它不保证可靠应用层要能处理超时、丢包、响应解析失败等情况。这个项目最大的收获是学习网络协议要从字节层面理解。只会调用 API遇到问题时容易停在表面知道报文结构才能解释为什么一个域名要这样编码为什么响应里可能有压缩指针为什么同样是网络通信DNS 和 HTTP 的处理方式完全不同。学习链接: https://github.com/0voice