IP 只做一件事:把包从源地址送到目的地址。 它不重传、不排序、不保证到达——这三件事全推给上面的 TCP。
上一节跟一个字节走完全程,这一节单独看网络层那一段。IP 的「不负责」正是 HTTP 需要 TCP 的原因。
一、IP 头里有什么、没有什么
20 字节固定头里,关键字段只有五组:版本、首部长度、总长度、TTL、协议号, 再加上源地址与目的地址各 4 字节。 没有序号、没有确认号、没有重传计时器。 因为 IP 是「尽力而为」(best effort):能送到就送,送不到就算了。 这套设计的好处是简单——路由器只需要查表转发,不需要为每条连接维护状态。 全世界的骨干网能跑这么快,一半功劳在这个「不管」上。
二、地址为什么必须分层
IP 地址由「网络部分 + 主机部分」组成,中间用掩码划开。
这不是为了好看,是为了路由表能压缩:路由器只需要记「10.0.0.0/8 走这个口」,
不用记一千万台主机。
Demo 里本机出口地址是 192.168.3.152,属于私网段。
私网地址不能直接在公网路由,出去要经过 NAT 换成公网地址。
NAT 让 IPv4 多活了二十年,代价是端到端被破坏——外面的机器没法主动连进来,
这也是 P2P 和实时通信要打洞的原因。
三、分片:MTU 是硬约束
每种链路都有自己的最大传输单元。以太网 1500,PPPoE 少 8 字节,某些隧道再少 20 到 60 字节。 超过就必须分片。 分片很贵:每片都要重复 20 字节 IP 头,而且丢任何一片整个包都要重传。 所以现代做法是尽量避免分片——TCP 用 MSS 协商,路径上再用 PMTUD 探测, 遇到「不分片」标志就回 ICMP 让你改小。 经典故障:中间设备把 ICMP 全拦了,PMTUD 探不出来,大包全丢、小包正常,登录取密码页能开、 提交就卡死。这叫 MTU 黑洞。
四、动手 Demo:本机出口地址、MTU 与 IP 头的开销
取本机在默认路由上的地址(不发包,只看内核选哪张网卡),判断是不是私网, 再算 IP 头在不同 MTU 下的占比。
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((u'8.8.8.8', 53)) # UDP connect 不发包
ip = s.getsockname()[0]
priv = ip.startswith(u'10.') or ip.startswith(u'192.168.')
for mtu in (1500, 9000):
print(mtu, u'能装 TCP 数据', mtu - 20 - 20)
实跑输出:
--------------------------------------------------------------------
IP 只管把包送到,不管送到之后怎样
--------------------------------------------------------------------
本机出口地址 192.168.3.152
是否私网地址 是
IP 头固定部分 20 字节(最长 60,选项最多 40)
TTL 默认值 通常是 64 或 128,每过一个路由器减一
MTU 1500 能装的 TCP 数据 1460 字节
MTU 9000 能装的 TCP 数据 8960 字节
1 字节请求占 IP 净荷 20 + 20 + 1 = 41 字节
IP 头占比 48.8%
IP 是「尽力而为」:它不重传、不排序、不保证到达,这三件事全部推给上面的 TCP。
所以 IP 头里没有「序号」「确认号」——只有地址、长度、TTL 和校验和。
UDP connect 只设置目的地址、不产生任何报文,所以这一行既拿到了地址又没打搅网络。
MTU 1500 能装的 TCP 数据 1460、MTU 9000 能装的 TCP 数据 8960——两个数都是「减掉 40」,
这 40 字节在每一跳上都要重复占用带宽。
1 字节请求占 IP 净荷 41 字节、IP 头占比 48.8%——极端例子,但它说明短报文有多吃亏。
30 秒实验
- 把
8.8.8.8换成192.168.1.1,看出口地址变不变(大概率不变)。 - 算一算:MTU 1500 下,一个 4000 字节的 TCP 报文会被分成几片、每片多少字节。
- 查一下自己机器的网卡 MTU(
netsh interface ipv4 show subinterfaces),看有没有不是 1500 的。
常见误区
- 「IP 保证送到」——只保证尽力,丢了不赔。
- 「IP 地址就是设备编号」——它是「网络位置」,换网络就得换地址。
- 「分片是路由器的事,客户端不用管」——分片会大幅降低效率,而且中间设备常常直接丢弃分片包。
自测三问(点开对答案)
1. IP 头里为什么没有重传相关字段? —— 因为它不做重传。可靠性由上层 TCP 自己实现。 2. 私网地址为什么不能直接上网? —— 公网路由器不为私网段维护路由,必须经 NAT 换成公网地址。 3. MTU 黑洞是怎么形成的? —— 路径上某段 MTU 更小,而 ICMP 又被拦截,PMTUD 探不到,导致大包全被丢弃。IP 把包送到了,但送的过程可能乱序、可能丢。下一节看 TCP 怎么把这些补回来。
- ☐ (本节完,下一节 1.4.2 确保可靠性的TCP协议)
相关笔记
- 12 课 · 计算机网络(IP 地址、掩码与路由表)
- 📘 图解HTTP · 索引