假设电脑 A(192.168.12.170/26)要给同子网的电脑 B(192.168.12.180)发数据。路由表告诉电脑 A 可以直接发,但要把 IP 包封成以太网帧发出去,帧头里还得填目的网卡的 MAC 地址。在局域网里根据下一跳 IPv4 地址查对应 MAC 地址的协议就是 ARP(Address Resolution Protocol,地址解析协议)。
ARP 请求与应答
- 广播 ARP 请求:电脑 A 不知道电脑 B 的 MAC 地址,就在局域网里发一条广播询问:“谁是
192.168.12.180?请把你的 MAC 地址告诉192.168.12.170。”以太网帧头的目的 MAC 填广播地址ff:ff:ff:ff:ff:ff。 - 交换机泛洪广播:交换机把广播帧发给同一广播域里的所有端口,局域网里的每台设备都能收到。
- 单播 ARP 应答:电脑 B 发现问的是自己,就单独给电脑 A 回一条单播应答:“我是
192.168.12.180,我的 MAC 是02:00:00:00:01:20。”其他设备发现问的不是自己,直接丢弃。 - 写入缓存并发送数据:电脑 A 把
192.168.12.180 → 02:00:00:00:01:20记进本地 ARP 缓存表,然后再把业务数据封成目的 MAC 为02:00:00:00:01:20的以太网帧发出去。
在 Linux 里可以用 ip neigh 查看当前的 ARP 缓存表(lladdr 就是对方的 MAC 地址):
crow@laptop:~$ ip neigh
192.168.12.180 dev enp1s0 lladdr 02:00:00:00:01:20 REACHABLE
跨网段通信时 ARP 查的是谁?
如果电脑 A 要访问的是另一个网段的服务器 192.168.20.10,路由表会告诉它下一跳是默认网关 192.168.12.129。这时候,电脑 A 发起 ARP 请求查的是默认网关 192.168.12.129 的 MAC 地址,而不是远端服务器 192.168.20.10 的 MAC 地址。
封出来的以太网帧里:
- IP 头部:源 IP 是本机 A,目的 IP 是最终服务器
192.168.20.10(表示包最终要去哪)。 - 以太网帧头:源 MAC 是本机 A,目的 MAC 是默认网关
.129的 MAC(表示当前这一跳交给谁)。
网关收到帧后拆掉二层帧头,拿出里面的 IP 包,再查自己的路由表往下一跳发。ARP 广播出不了本地局域网(路由器不转发 ARP 广播)。另外,ARP 只用于 IPv4;IPv6 改用基于 ICMPv6 的邻居发现协议(NDP)来查二层地址。
ARP 缓存表与交换机 MAC 表
主机的 ARP 缓存表和交换机的 MAC 地址表名字很像,但存的东西和用途完全不同:
| 表名 | 保存在哪 | 映射关系 | 解决什么问题 |
|---|---|---|---|
| ARP 缓存表 | 主机、路由器 | IPv4 地址 → MAC 地址 | 封装以太网帧时,目的 MAC 该填谁 |
| MAC 地址表 | 交换机 | MAC 地址 → 交换机端口 | 交换机收到以太网帧后,该从几号网口发出去 |