IP 发之前不打招呼,每个包独立选路——省掉的是「建链」那段时间。 代价是「不保证送到」,而这个代价在高延迟链路上会变得非常明显。
4.2.3 讲「IP 不关心底层」,这一节讲「IP 也不关心上一个包」。 2.1.3 说过「可靠归 TCP」,这一节把「不可靠」这件事的账算清楚。
一、省掉的是建链
面向连接和无连接,区别就在「发之前要不要先谈一次」:
| 项目 | 面向连接 | 无连接 |
|---|---|---|
| 建链 | 要,1.5 个往返 | 不要 |
| 状态 | 两端都记着 | 不记 |
| 丢了 | 自动重传 | 自己处理 |
第一行那个「1.5 个往返」是 TCP 三次握手的代价:一次 SYN、一次 SYN-ACK、一次 ACK, 前面两次要等对方回,所以是「一来一回半」。 这个开销和「距离」成正比——局域网里几乎免费,卫星链路上就是整整一秒。 第三行是无连接的真正代价:包丢了没人管,顺序乱了自己排。 所以「IP 不可靠」不是缺陷,是「把可靠性交给需要它的人」—— 视频通话不需要重传(晚到的帧没用),文件传输需要。 一个协议如果强制全都可靠,视频就会被重传拖死。
二、算一下这笔钱
在四种延迟下,建链要花多久:
| 往返 | 握手代价 | 连带两次收发 |
|---|---|---|
| 1 ms | 1.5 ms | 3.5 ms |
| 10 ms | 15 ms | 35 ms |
| 30 ms | 45 ms | 105 ms |
| 600 ms | 900 ms | 2100 ms |
第一行是局域网,握手几乎不花时间,所以「面向连接」在那里是免费的,还白拿可靠性和顺序。 第四行是同步轨道卫星, 光建链就要 900 毫秒——这就是「卫星上网点一个链接要等一秒」的由来。 第三列是「加两次实际收发」之后的总延迟: 它才是用户感受到的那个数(点链接到看见第一个字节)。 所以「延迟高」这件事不是被放大一次,是被放大好几倍——因为每个交互动作都要付一次往返。
三、为什么这样设计
回到 2.1 那句话:IP 的目标是「把包送到,尽力而为」,它不承诺质量,只承诺「努力」。 这个「尽力而为」的定位带来三个好处:
| 好处 | 具体表现 |
|---|---|
| 路由器不用记状态 | 每个包独立转发,坏了换一台就行 |
| 可以随时换路 | 一条路断了,下一个包走别的 |
| 实现极简 | 路由器只做「查表、转发」两件事 |
第一行是「可扩展」的根源:如果每个连接都要在路由器上记状态, 那么「一百万人同时上网」就意味着每台骨干路由器要记几百万条状态—— 这在 1970 年代的设备上根本做不到。 第二行是「抗故障」的根源: 面向连接的网络(比如 ATM、帧中继)一旦链路断了,所有经过它的连接都要重建; 而无连接的网络只需要「路由表更新一下」,后续的包自动绕路。 所以「IP 能承受部分网络瘫痪」这件事,是「无状态」换来的。 第三行是「便宜」的根源: 路由器不需要维护连接表,内存和 CPU 都省——这就是为什么 IP 设备能做得又便宜又快。
四、动手 Demo:无连接省下的那点时间,值多少钱
把「三次握手」的代价在四种往返延迟下算出来,再加上两次实际收发。 注意最后一行:600 毫秒往返,总延迟 2.1 秒。
for rtt in (1, 10, 30, 600):
print('往返 %4d ms 握手 %7.1f ms 连带收发 %8.1f ms'
% (rtt, rtt * 1.5, rtt * 1.5 + rtt * 2))
实跑输出:
--------------------------------------------------------------------
无连接省下的那点时间,值多少钱
--------------------------------------------------------------------
**IP 是「面向无连接」的:发之前不打招呼,每个包独立选路。**
**代价是「不保证送到」,收益是「没有建立连接的开销」。**
项目 TCP(面向连接) UDP 与 IP(无连接)
----------------------------------------------------------------
**要不要建链** **要,1.5 个往返** **不要**
**每个包独立吗** **不独立,有状态** **独立**
**丢了怎么办** **自动重传** **自己处理**
**算一下「建链」这笔开销**:
往返延迟 三次握手的代价 加两次收发的总延迟
---------------------------------------------------
1 ms 1.5 ms 3.5 ms
10 ms 15.0 ms 35.0 ms
30 ms 45.0 ms 105.0 ms
600 ms 900.0 ms 2100.0 ms
**第一行 1 毫秒的局域网,建链只要 1.5 毫秒,几乎无所谓。**
**第四行 600 毫秒的卫星链路,光建链就要 900 毫秒**——
**这就是「卫星上网点一个链接要等一秒」的由来。**
**所以「无连接」不是「更先进」,是「在延迟高的链路上更划算」。**
**而「面向连接」在局域网里几乎免费,还白拿可靠性和顺序保证**——
**这就是为什么同一个网络里,两种都要有。**
「1.5 个往返」这个系数值得记一下:SYN 出去、SYN-ACK 回来是一个往返,最后的 ACK 不用等回, 所以是 1.5。 而 TLS 握手还要再来一到两次往返——所以「HTTPS 首次连接慢」在卫星链路上是「好几秒」。 「连带两次收发」这个算法是粗略的:实际还要算上「服务器处理时间」和「拥塞窗口爬升」。 特别是后者:TCP 的慢启动每轮往返才翻一倍窗口,600 毫秒的往返意味着「传满带宽要好几十秒」。 这就是 3.7.9 讲的「高延迟链路吞吐上不去」。 最后说清一个常见的误解:「UDP 快」不是因为它的头小(那 8 个字节无关紧要), 是因为它「不用等建链、不用等确认」。 所以「用 UDP 打游戏快」的本质是「少等往返」,不是「协议更高效」。
30 秒实验
- 算一下:往返 100 ms 时,握手加两次收发一共多久?
- 想一下:为什么视频通话可以用 UDP,而文件下载不行?
- 想一下:如果路由器要记住每个连接,最直接的成本是什么?
常见误区
- 以为「IP 不可靠是缺陷」。 是分工:可靠性交给需要它的上层(TCP)。
- 以为「UDP 快是因为头小」。 快在「不用建链、不用等确认」,8 字节头的差别可以忽略。
- 以为「面向连接一定更好」。 它要路由器记状态,规模一大就撑不住。
自测三问(点开对答案)
1. 无连接省掉的是什么? —— **建链那 1.5 个往返,以及路由器上的连接状态**。 2. 为什么高延迟链路上「无连接」更划算? —— **建链的代价和往返成正比**,往返越大,省下的越多。 3. IP 的三个「尽力而为」好处是什么? —— **路由器不记状态、可以随时换路、实现极简**。下一节开始讲 IP 地址本身:32 位怎么写成四个数字。
- ☐ (本节完,下一节 4.3.1 IP地址的定义)