📚 第四章 IP协议
📄 一句话概括

第 3 层管「终点在哪」,第 2 层管「这一跳交给谁」——这是全书最重要的一条分界线。 路由器只查不改 IP 头,却要重写每一次的链路层头。

📝 本节和前面几节的关系

第三章讲的全是「这一跳」,从这一章开始讲「终点」。 3.1 那句「不管最终去哪」在这里得到兑现:接手的这个人就是 IP。

一、一个包在路上

把一次「从你的电脑到服务器」拆开看,变化的东西只有一样:

位置 源 MAC 目的 MAC IP 头
主机 A 网卡 本机网卡 路由器 1 不变
路由器 1 出 路由器 1 右口 路由器 2 不变
路由器 2 出 路由器 2 右口 服务器 不变

第三列一直在换,第四列一直没动:这就是「链路层地址只管这一段」的直接证据。 每过一台路由器,链路层头就被拆掉重写一遍,而 IP 头从头到尾是同一个。 所以「经过的跳数越多,链路层越忙,网络层越省」: 中间设备只需要看它该看的那一层——交换机看 MAC,路由器看 IP,各干各的。

二、分界线的准确位置

三层各管什么,一句话能说清:

层 地址 管到哪 谁看
第 2 层 MAC 一段链路 交换机
第 3 层 IP 整条路径 路由器
第 4 层 端口号 一台主机内 主机自己

第一行的「一段链路」是精确的说法:不是「一个网段」,是「一条物理上能直达的信道」。 所以两台主机之间如果隔了一台路由器,它们就不在「一段链路」上——哪怕 IP 网段是同一个。 第二行的「整条路径」也是精确的:IP 地址从源到目的都不变, 所以它描述的其实是「终点」,而不是「怎么走」。 「怎么走」是路由表的事——同一对源和目的,换个时间可能走不同的路,但 IP 头是一样的。

三、为什么这样分

分成两层的收益只有一条,但足够大:中间设备不用知道全局。 交换机只需要一张 MAC 表,不用知道互联网有几十亿个地址; 路由器只需要一张路由表,不用记住每台主机的 MAC。 如果只有一个地址体系会怎样: 要么所有设备都用 MAC 寻址,那路由器就得存下全球每一块网卡的地址(不可能); 要么所有设备都用 IP 寻址,那每次换网卡都要改 IP(也不合理)。 所以这条分界线的本质是「信息的分布」:MAC 是硬件出厂就定好的、不可聚合的编号; IP 是可以按前缀聚合的、有层次的编号。 只有「可聚合」,路由器才可能用一张几千条的表覆盖整个互联网。 顺带说一句「第 3 层」这个编号:OSI 的七层里,网络层是第三层, 所以「三层设备」指的就是路由器,「二层设备」指交换机—— 这两个说法在工程里天天用,来源就在这里。

四、动手 Demo:一个包在路上,哪一层在变

把一次跨三台路由器的传输摊开,看每一段用的是哪个地址。 注意最后一列:IP 头从头到尾「不变」。

hops = [('主机 A 网卡', '9C-B6-..-0F', '路由器 1'),
        ('路由器 1 出', '路由器 1 右口', '路由器 2'),
        ('路由器 2 出', '路由器 2 右口', '服务器')]
for where, src, dst in hops:
    print('%-14s 源 MAC %-12s 目的 MAC %-10s IP 头 不变'
          % (where, src, dst))
print('链路层头重写 %d 次,IP 头重写 0 次' % len(hops))

实跑输出:

--------------------------------------------------------------------
一个包在路上,哪一层在变
--------------------------------------------------------------------
**同一个包从你的电脑到服务器,IP 头只被「看」不被改,而链路层的头每过一台路由器就要换一次。**
**这就是「第 3 层管终点、第 2 层管这一跳」的具体样子。**

  位置            这段的源 MAC      这段的目的 MAC     IP 头
  --------------------------------------------------------------
  主机 A 网卡     9C-B6-..-0F       路由器 1           **不变**
  路由器 1 进     路由器 1 左口     路由器 1           **不变**
  路由器 1 出     路由器 1 右口     路由器 2           **不变**
  路由器 2 出     路由器 2 右口     服务器             **不变**

**第三列一直在换,这才是「第 2 层地址」的含义**:**它只在「这一段」有效,换一段就重写。**
**而第四列的 IP 头从头到尾没动**——**它是「终点地址」,路由器只查不改(NAT 除外)。**

**算一下这个包被改了几次**:
**链路层头重写 4 次,IP 头重写 0 次,TCP 头重写 0 次。**
**所以「经过的跳数越多,链路层越忙,网络层越省」**——
**这是分层最直接的收益:中间设备只需要看它该看的那一层。**

「路由器只查不改 IP 头」这句话有个例外要说清:NAT 会改,而且改得很彻底(源地址、 源端口都换)。所以严格说「IP 头不变」只在「没有 NAT」的前提下成立。 但 NAT 是「网络边缘的一次性改写」,不是「每一跳都改」—— 这个区别很重要,否则会把 NAT 和路由混为一谈。 还有一个会改 IP 头的设备:防火墙的「地址转换」和「代理」。 代理是「重新发一个请求」,连 TCP 连接都是新的,而 NAT 是「只改头部字段、连接还是那条」。 两者的区别在于「谁在维持状态」。 最后记一个术语:「逐跳转发」这个词就是这个机制的正式名字。 每一台路由器只负责「把包交给下一个更接近终点的设备」, 它不需要知道完整路径——这和「源路由」(把整条路径写进包里)是相反的两种设计。

30 秒实验

  1. 想一下:如果只用 MAC 地址通信,路由器需要多大的表?
  2. 想一下:为什么「IP 地址不变」这句话在 NAT 场景下要打折扣?
  3. 在你电脑上 tracert 一个网站,数一下中间经过几台路由器。

常见误区

  1. 以为「IP 地址每一跳都会变」。 不变,变的是链路层地址。变的那个叫 NAT。
  2. 以为「MAC 只管一个网段」。 是「一段链路」,同一网段里隔了路由器就不算同一段链路。
  3. 以为「分层是为了好看」。 是为了「中间设备不用知道全局」,这才是它能扩展的前提。
自测三问(点开对答案) 1. 第 3 层和第 2 层的分工线在哪? —— **第 2 层管「这一跳交给谁」,第 3 层管「终点在哪」**,所以前者每跳都换、后者全程不变。 2. 为什么 MAC 地址不能当全球地址用? —— **它是平铺的、没有层次**,路由器无法用它聚合出「一大片去哪儿」。 3. 分层带来的最大收益是什么? —— **中间设备不用知道全局**:交换机只要 MAC 表,路由器只要路由表。

下一节把这两层的关系再拧紧一点:IP 和 MAC 怎么配对。

相关笔记