首发: Rice 嵌入式开发技术分享
作者:RiceDIY
背景
- 因特网上的节点通过IP地址唯一标识,并且能通过IP地址来识别参与分布式应用的主机。但对于大多数人来说,这些地址太繁琐而且难以使用和记忆(特别是IPV6地址)。因此互联网支持使用主机名称来识别包括客户机和服务器在内的主机。为了使用如TCP和IP等协议,主机名称可以通过称为域名解析的过程转换成IP地址。
- 在互联网中存在不同形式的名称解析,但是最普遍、最重要的一种是采用分布式数据库系统,即我们熟知的域名系统(DNS),也是这篇文章的主角。
- DNS - 是一个分布式的客户机-服务器网络数据库,TCP/IP应用程序使用它来完成主机名称和IP地址之间的映射,提供电子邮件路由信息、服务命名和其他服务。
- DNS使用TCP和UDP的端口--53。
- DNS - 为了可扩展性,DNS名称是分层的。每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。
- 下面来介绍DNS报文的格式解析,以及如何将域名转为IP地址的流程。
准备工具
DNS报文解析
抓包分析
- 打开CMD和WireShark工具。
- 在WireShark中设置过滤信息,我们只抓取DNS报文。
- 在CMD键入ping www.baidu.com,然后查看WireShark的抓包信息。
- 可以看到两包DNS报文,一个是DNS发送报文,一个是DNS接收报文
- 发送报文
- 接收报文
- 发送报文和接收报文格式是不一样的,从上面截图可以看到,接收报文多一个Answers字段。
- DNS可以使用UDP与TCP两种协议。这里我们主要以UDP进行分析。
DNS报文字段解析
- DNS报文格式:
- DNS字段格式:
- 发送报文
- 接收报文
DNS报文头部
- 字段说明
- 代码实现
/** DNS message header */
DNS报文问题字段
- 字段说明
- 查询名称格式:
- 代码实现
struct dns_answer {
DNS报文发送实现
- 代码实现
static void dns_packet_output(uint8_t *host_name)
- 验证代码结果,我们通过查询CSDN的IP地址,CSDN的域名:www.csdn.net
- 通过wireshark抓包,可以看到我们DNS报文已发送成功,并且有应答包
DNS报文接收实现
- 代码实现
static void dns_packet_input(void *dns_packet_data)
- 通过wireshark抓包的IP与代码捕获的IP一致:
UDP协议栈系列篇阅读
更多嵌入式技术干货请关注Rice 嵌入式开发技术分享