上一篇里我们跟着浏览器走到了这一步DNS 查出了网站的 IP 地址电脑准备发送请求。问题来了。假设网站服务器的 IP 地址是203.0.113.10你的电脑知道这个地址就能直接把数据发过去吗不能。服务器可能远在另一个城市而你的电脑眼前只有家里的网络。它要先把数据交给家里的路由器请路由器继续往外送。目标是网站服务器第一站却是家里的路由器。理解这一点MAC 地址、ARP 和交换机就不再是三个孤立的名词。文中的 IP 和 MAC 地址都是示例。你家网络里的实际地址可能不同。一份数据为什么需要两种地址假设你家的网络是这样电脑 IP192.168.1.20 │ │ 家庭局域网 ▼ 路由器 局域网 IP192.168.1.1 │ │ 互联网 ▼ 网站服务器 IP203.0.113.10电脑要访问的是网站服务器所以发出的 IP 数据包里目标 IP 是203.0.113.10。但电脑不能越过眼前的网络设备把数据直接塞到服务器手里。它得先把这份 IP 数据包交给路由器。在家庭局域网这一段它需要知道路由器的MAC 地址。两种地址管的是不同的事目标 IP 地址这份数据最终要去哪里目标 MAC 地址在当前这段网络里先交给谁所以发往网站的第一段数据完全可能同时写着目标 IP 203.0.113.10 ← 最终要找的网站服务器 目标 MAC路由器的 MAC 地址 ← 当前这一段先交给路由器这不是写错了两个目的地而是分别回答了“最终去哪儿”和“眼前交给谁”。MAC 地址是什么MAC 地址是网络接口在局域网通信中使用的一种地址常见写法像这样02:11:22:33:44:55电脑里的有线网卡、无线网卡以及路由器的网络接口都可以有各自的 MAC 地址。这里说“路由器的 MAC 地址”更准确地说是路由器面向你家局域网的那个接口的 MAC 地址。不要把 MAC 地址理解成设备永久不变的身份证号。设备可能有多个网络接口手机也可能使用随机化的 Wi-Fi MAC 地址。对我们今天的问题来说重要的是发送数据时电脑需要一个能在当前网络中使用的下一站地址。那么电脑知道路由器的 IP 是192.168.1.1怎样找到它的 MAC 地址ARP问一句“谁是 192.168.1.1”在 IPv4 局域网里完成这件事的常见办法是 ARP。电脑先查看自己的 ARP 缓存。如果里面已经记录了192.168.1.1对应的 MAC 地址就可以直接使用。如果没有它会在本地网络里发出一条查询大意是谁拥有192.168.1.1请告诉我你的 MAC 地址。这条查询是广播同一广播范围内的设备都可能收到。其他设备发现问的不是自己就不作答路由器发现问的是自己的局域网 IP就回复自己的 MAC 地址。电脑收到回复后把这组对应关系暂时记在 ARP 缓存里。过程可以画成这样电脑谁是 192.168.1.1 │ ├── 发给本地网络中的设备 │ └── 路由器我是。我的 MAC 地址是 02:aa:bb:cc:dd:ee。 │ ▼ 电脑记录 IP 与 MAC 的对应关系ARP 查的是本地下一站的地址不是替 DNS 再查一遍网站地址。DNS 回答“example.com对应什么 IP”ARP 回答“本地的192.168.1.1对应什么 MAC”。两次查询看起来都在“找地址”找的却不是同一种地址。ARP 广播也不会一路传遍互联网。它只在当前的本地网络范围内起作用。到了另一个网络需要由那里的设备处理它自己这一段的交接。这里讨论的是 IPv4IPv6 使用邻居发现机制来完成相应的工作不照搬 ARP。查到 MAC 后电脑发送的是什么电脑要发送的是一个IP 数据包。为了让它能在当前这段网络上传输网卡会再给它加上链路层的信息形成一份可以交给下一站的帧。先看一个简化示意帧 ├─ 目标 MAC路由器的 MAC ├─ 来源 MAC电脑网卡的 MAC └─ 装载的数据 └─ IP 数据包 ├─ 目标 IP网站服务器的 IP └─ 其他数据这就是上一篇提到的“封装”IP 数据包没有消失而是被放进了当前网络使用的帧里。如果电脑接的是网线这里可以理解为以太网帧。如果用的是 Wi-Fi无线链路上的帧格式会有所不同但今天要抓住的逻辑仍然成立先解决当前这一段如何交接再由路由器处理下一段。路由器收到发给自己的帧后会取出其中的 IP 数据包查看目标 IP然后决定往哪里继续转发。进入下一段网络时又会使用适合下一段网络的链路层信息。因此发给网站服务器的 IP 目标与第一段使用的目标 MAC并不需要相同。MAC 地址也不会像写在包裹上的最终收件地址那样从你家一直用到网站机房。交换机在中间做了什么家里如果有多台有线设备它们可能接在交换机上。很多家用路由器也集成了交换功能所以你未必见过一台单独的交换机。交换机的工作重点是把收到的帧送向正确的接口。它会从经过自己的帧中学习“这个来源 MAC 地址是从哪个接口进来的”久而久之它就有了一张 MAC 地址表。收到发往某个 MAC 地址的帧时如果表里知道该地址在哪个接口就从相应接口转发。如果暂时不知道目的 MAC 在哪里交换机可能会在所属的本地网络范围内向其他相关接口转发等待目标设备回应。前面电脑发送的 ARP 广播也会通过这种本地转发到达路由器。交换机和路由器因此有不同的关注点交换机主要依据 MAC 地址处理当前局域网中的帧。路由器主要依据 IP 地址决定数据包怎样前往其他网络。家用设备把这些功能装在一个盒子里不代表它们做的是同一件事。如果访问的是家里另一台电脑呢假设你要访问的不是互联网上的网站而是家里另一台电脑IP 为192.168.1.30。你的电脑会根据自己的网络配置判断这个地址能否在本地直接到达如果可以它要查找的就是192.168.1.30对应的 MAC 地址然后把数据直接交给那台电脑不必先把它交给路由器去转发。这也解释了为什么前面的例子要先找路由器网站服务器不在家里的局域网中电脑需要一个能带它离开本地网络的默认网关。家用网络里这个网关通常就是路由器。“怎样判断两个 IP 是否在同一个子网”会涉及 IP 地址和子网掩码我们放到下一篇仔细算。在自己的电脑上验证一次下面以 Windows 为例。打开命令提示符输入ipconfig找到当前正在使用的网卡记下它的IPv4 地址和默认网关。默认网关可能是192.168.1.1也可能是别的地址以你电脑上的结果为准。接着输入arp -a在输出中寻找默认网关的 IP。你可能会看到类似这样的对应关系Internet Address Physical Address Type 192.168.1.1 02-aa-bb-cc-dd-ee dynamic左边是网关的 IP右边是电脑记录的 MAC 地址。如果暂时没看到可以先尝试ping 你的默认网关IP然后再运行一次arp -a。即使网关没有回复ping电脑在尝试发送数据时也可能已经解析出了它的 MAC 地址具体结果取决于你的网络设备和系统。用 macOS 或 Linux 的读者可以先用ip route、route -n get default等命令找到网关再查看系统的邻居缓存。命令外观不同要找的仍是同一件事本地网关的 IP 与链路层地址之间的对应关系。现在再看上一篇那条“电脑 → 路由器 → 网站服务器”的线它应该更具体了电脑知道网站的 IP ↓ 判断网站不在本地决定先交给网关 ↓ 用 ARP 找到网关的 MAC ↓ 把 IP 数据包装进本地传输的帧 ↓ 通过 Wi-Fi 或交换机交给路由器 ↓ 路由器继续处理通往外部网络的下一段今天真正需要记住的不是某个 MAC 地址长什么样而是这条规则IP 指向最终目标每走一段本地网络还得解决“这一段交给谁”。下一篇我们就来回答电脑作出判断时最关键的问题它凭什么知道一个 IP 在不在本地网络子网掩码究竟怎么算参考资料ARP 规范 RFC 826、IPv6 邻居发现规范 RFC 4861、Cisco 交换机 MAC 地址学习说明。