我们知道,网络层使用的是 IP 地址,而在实际网络的链路上传送数据帧时,最终还是必须使用链路层的 MAC 地址。所以,在链路上传送数据帧时只知道 IP 地址是不够的,我们还需要知道主机在网络中的有效 MAC 地址,那么有没有什么办法可以把 IP 地址转换为物理地址呢?那就要用 地址解析协议(ARP) [RFC0826] 来解决这个问题了。
地址解析协议(Address Resolution Protocol, ARP) 是一个通用的协议,从这个意义上来看,它被设计为支持多种地址之间的映射。也就是说 ARP 提供从网络层地址到相关硬件地址的动态映射。实际上, ARP 几乎总是用于 32
位 IPv4 地址和以太网的 48
位 MAC 地址之间的映射。
这里有一点需要注意, ARP 仅用于 IPv4 , IPv6 使用 邻居发现协议(NDP) ,它被合并入 ICMPv6 。
另外,还有一个提供 ARP 反向映射的协议称为 逆地址解析协议(RARP) ,它能让知道自己 MAC 地址的主机通过 RARP 找出其 IP 地址,它在当前已很少使用。
在每个主机中都有一个 ARP 高速缓存 ,该缓存使用地址解析为每个接口维护从网络层地址到硬件地址的最新映射,里面存放的是所在局域网上的各主机和路由器的 IP 地址到硬件地址的映射表。每一个 IPv4 地址映射到硬件地址对应于高速缓存中的一个条目,其有效时间为条目创建开始后的 20 分钟 [RFC1122] 。
在 Linux
或者 Windows
中我们可以使用 arp
命令查看 ARP 缓存 。例如,在我的 Windows 系统下查看 ARP 缓存如下。
C:\>arp -a
接口: 192.168.56.1 --- 0x8
Internet 地址 物理地址 类型
192.168.56.255 ff-ff-ff-ff-ff-ff 静态
...(后面省略)
在上述的例子中,显示了接口的 IPv4 地址 192.168.56.1
,而后跟着的是接口号 0x8
,这里用的是十六进制表示。当然,还给出了该条目的类型,如果是通过手工输入的就是静态的,来自 ARP 学习就是动态的,上面给出的例子是 静态
的。
再例如,我的 Linux 系统下查看 ARP 缓存如下。
caizi@ubuntu:~$ arp
Address HWtype HWaddress Flags Mask Iface
192.168.152.1 ether 00:50:56:c0:00:08 C ens33
...(后面省略)
在上述的例子中,每个映射条目都包含了 5
个元素,分别是 Address(主机名) 、 HWtype(硬件地址类型)、 HWaddress(硬件地址) 、Flags Mask (标志)、Iface(本地网络接口)。
其中,Flags Mask (标志) 包含一个符号, C 、 M 或 P。C 类条目由 ARP 协议动态学习,M 类条目由手工进行输入。P 类条目表示该缓存条目是“发布的”。对于任何 P 类的缓存条目,主机对输入的 ARP 请求都返回一个 ARP 响应。该选项用于配置代理 ARP 。
通过上面两个不同系统下 ARP 高速缓存表的显示还能发现,在 Linux 系统下 48 位的 MAC 地址是用 冒号 进行分隔的,而在 Windows 系统下是用 短杆 进行分隔的。传统上, UNIX 系统一直使用冒号,而 IEEE 标准和其他操作系统更倾向于使用短杆。
参考文献:
[1] Fall, K. R., and Stevens, W. R. TCP/IP详解 卷1:协议. Translated by 吴英, 张玉 and 许昱玮, 2nd ed., 机械工业出版社, 2016.