IP 只把包送到「主机」,送到哪个程序是传输层的事:所以它必须有「分用」的能力。 端口就是这个「分用」的标识,一台主机靠它同时跑几百个网络程序。
第四章讲的 IP 到「主机」为止,这一章开始讲「到程序」。 5.1 提过「IP 只负责送」,这一节把它补完整:送完之后谁来接。
一、IP 交付的边界在哪
IP 首部里只有「源地址」和「目的地址」,没有「给哪个程序」这一项。 所以 IP 的交付粒度是「一台主机」,它把包放下就走。 这在早期没问题:一台机器只跑一个网络程序,放下就是给它的。 但很快就不行了——浏览器、邮件、聊天同时开着,三个程序都等着收包,谁来分? 传输层就是干这个的: 它在 IP 之上再加一层「谁收」的标识,把「主机到主机」细分成「进程到进程」。 这个动作有个术语叫「分用」(demultiplexing)——收到包之后按标识分给对应的程序。
二、传输层补的三件事
它补的不只是「分用」,而是三件 IP 不管的事:
| 补什么 | IP 的做法 | 传输层的做法 |
|---|---|---|
| 交给谁 | 只到主机 | 用端口找到进程 |
| 数据对不对 | 只校验首部 | 校验整段(可选) |
| 要不要连接 | 无连接 | TCP 建,UDP 不建 |
第一行是必需的,第二行是「加保险」,第三行是「选择题」。 所以传输层不是一个协议,而是一族协议:TCP 三样全要,UDP 只要第一样。 第二行容易被忽略:IPv4 的首部校验和只管首部,不管数据(4.7 算过); 所以「数据有没有错」这件事,IP 层是不管的。 传输层的校验和才是「端到端」的那一道——它从头到尾都没被中间设备改过。
三、端口是标识符,不是门
「端口」这个译名容易误导:它听起来像「物理接口」,实际只是一个 16 位的数字。 它的作用跟「学号」一样——用来在同一个人群里区分出具体的某一个。 所以「一台主机最多 65536 个程序同时通信」这个说法是错的: 端口是「同时存在的连接数」的上限,不是「程序数」的上限。 一个程序可以占很多端口(浏览器每个标签页都开连接), 多个程序也可以共用一个端口(比如多个进程共享 80)。 所以「端口数」和「程序数」根本不是一一对应的。
四、没有传输层会怎样
假设只有 IP:每台机器只能跑一个网络程序,而且「数据坏了」只能靠应用自己发现。 这就是传输层存在的全部理由——它不是「为了分层好看」,是因为「不分就没法用」。 反过来说:如果你的程序真的只需要「一台机器一个程序」,那传输层确实是多余的。 有些专用设备就这么干(比如某些工业控制的总线), 而通用计算机不行——因为「同时开好几个程序」是刚需。
五、动手 Demo:一台主机上到底有多少条连接
用 psutil 数一下本机此刻的连接,按状态分组。 注意它们共用同一个 IP,靠端口区分。
import psutil
from collections import Counter
cs = [c for c in psutil.net_connections(kind='inet') if c.status]
for k, v in Counter(c.status for c in cs).most_common():
print('%-12s %d' % (k, v))
实跑输出:
--------------------------------------------------------------------
一台主机上到底有多少条连接
--------------------------------------------------------------------
**IP 只负责把包送到「主机」,送到哪个程序是传输层的事。**
**所以「一条连接」比「一个 IP 地址」细得多。**
状态 条数
---------------------
NONE 59
LISTEN 47
ESTABLISHED 42
TIME_WAIT 37
CLOSE_WAIT 2
**本机此刻 187 条 inet 连接,共用同一个 IP**:
**区分它们的是「端口」,而不是地址。**
**这就是传输层存在的第一理由**——**没有端口,一台主机只能有一个程序在上网。**
**再看状态列**:**LISTEN 是「等着别人来连」,ESTABLISHED 是「已经连上」。**
**TIME_WAIT 是「主动关掉之后还在等一会儿」**,**数量多不代表故障,代表「短连接很多」。**
**第一行那个 NONE 不是错误**:**它是 psutil 给 UDP 打的标记**——**UDP 没有建立和关闭的过程。**
**所以「没有状态」就是它唯一的状态。**
**这一行恰好说明了两者的根本差别**:**TCP 有生命周期,UDP 只有「发」和「收」。**
这里数出来的是「连接」而不是「程序」:184 条连接背后可能只有十几个进程, 因为一个进程可以开几十条连接。 所以「端口够不够」要看连接数,不是看程序数。 「NONE」那一行是 UDP:UDP 没有建立和关闭的过程,所以「没有状态」。 这一行恰好说明了两者的根本差别:TCP 有生命周期,UDP 只有「发」和「收」。 「共用同一个 IP」这句话要落到实处:本机只有一块网卡在工作,所有连接都用同一个地址, 而「哪条连接是哪个程序」全靠端口加五元组区分——这就是传输层「分用」的具体做法。
30 秒实验
- 想一下:如果只有 IP,一台机器能同时跑几个网络程序?
- 算一下:65536 个端口,够不够一台机器开 10 万条连接?
- 想一下:为什么「端口数」不等于「程序数」?
常见误区
- 以为「IP 能把数据送到某个程序」。 它只送到主机,分给哪个程序是传输层的事。
- 以为「端口就是物理接口」。 它只是一个 16 位数字,作用类似学号。
- 以为「一台机器最多 65536 个程序」。 限制的是「同时的端口占用」,一个程序可以占很多个。
自测三问(点开对答案)
1. 传输层补了 IP 哪几件事? —— **交给哪个进程(端口)、数据对不对(校验和)、要不要连接(TCP 或 UDP)。** 2. 「分用」是什么意思? —— **收到包之后按端口标识,把它交给对应的进程**,把「主机到主机」细分成「进程到进程」。 3. IPv4 为什么还要靠传输层做校验? —— **IPv4 的首部校验和只管首部、不管数据**,所以数据有没有错,只有在传输层才管。下一节看数据从应用到网线,一路上被加了几层头。
- ☐ (本节完,下一节 6.1.2 通信处理)