分层的比方:经理交代一件事,要经过翻译、秘书、收发室,每层各包一层。 每层给这份数据起一个新名字——名字就是排障时的坐标。
1.5.1 讲的是「怎么套头」,这一节讲「各层各管一段」。 1.5.3 会给出 OSI 的正式七层,这一节还是比方。
一、两个公司的部门传话
书里的比方:A 公司经理要和 B 公司经理沟通:
| 角色 | 干的活 | 对应的层 |
|---|---|---|
| 经理 | 想说什么 | 应用层 |
| 翻译 | 译成对方听得懂的语言 | 表示层 |
| 秘书 | 约定通话时间、记录进度 | 会话层 |
| 收发室 | 贴单、交给快递 | 传输层/网络层 |
这个比方的高明处在「各管一段」:
经理不需要知道快递走哪条路,收发室也不需要知道信里写了什么。
每层只和上下相邻的两层打交道。
第二行那个「翻译」在 TCP/IP 里没有对应的一层:
这正是 OSI 与 TCP/IP 最大的分歧——
OSI 认为编码转换该由协议栈统一管,TCP/IP 认为交给应用自己办。
结果是应用各自发明了 charset、Content-Encoding 这些字段,同一个问题被解决了几十遍。
二、同一份数据,五个名字
在数据上看到的「分层」,就是名字在变:
| 层 | 英文名 | 典型称呼 |
|---|---|---|
| 应用层 | message | HTTP 请求/应答 |
| 传输层 | segment/datagram | TCP 段/UDP 数据报 |
| 网络层 | packet | IP 包 |
| 链路层 | frame | 以太网帧 |
| 物理层 | bit | 电/光信号 |
第二行有两套名字不是笔误:TCP 的叫「段」(segment),UDP 的叫「数据报」(datagram), 因为 TCP 是流、UDP 是独立报文,性质不同。 混用这两个词的人,往往也没搞清 TCP 与 UDP 的差别。 第五行那个「比特」容易被跳过:物理层没有「报文」这个概念,它只有连续的信号。 所以物理层出的问题,表现是「误码率」而不是「丢包」——用词不同,查的方向就不同。
三、名字就是排障坐标
说话用哪个词,等于说「问题在哪一层」:
| 你听到的说法 | 指向的层 | 下一步查什么 |
|---|---|---|
| 「丢包」 | 网络层 | 路由、TTL、分片 |
| 「丢帧」 | 链路层 | 网线、双工、CRC 错 |
| 「超时」 | 传输层 | 重传次数、RTT |
| 「乱码」 | 应用/表示层 | 编码声明 |
这四行是排障时最省时间的一张表:因为「丢包」和「丢帧」在用户嘴里是同一句「网卡了」, 但根因、工具、负责人完全不同。 第四行那个「乱码」最能说明分层的价值:网络全程通、字节一个不差,可内容就是看不懂。 这说明底下四层全对,错在最上面的编码声明—— 有分层这个概念,你才能把「通不通」与「懂不懂」分开判断。
四、动手 Demo:同一份数据,在每一层有不同的名字
把五个层的名字、英文、典型称呼列出来。 这不是背单词,是把「说法」和「层」对应起来。
import _netsim as N
app = b'hello world'
seg = N.tcp4h(40000, 80, flags=0x18) + app
pkt = N.ip4h('192.168.3.152', '93.184.216.34', seg)
frm = N.eth('ff:ff:ff:ff:ff:ff', '9c:b6:d0:0d:d5:0f', pkt)
rows = [('应用层', 'message', 'HTTP 请求', len(app)),
('传输层', 'segment', 'TCP 段', len(seg)),
('网络层', 'packet', 'IP 包', len(pkt)),
('链路层', 'frame', '以太网帧', len(frm)),
('物理层', 'bit', '信号', len(frm) * 8)]
for zh, en, cn, n in rows:
print('%-8s %-16s %-12s %d' % (zh, en, cn, n))
print('链路层的帧再往下就是 %d 个比特' % (len(frm) * 8))
实跑输出:
--------------------------------------------------------------------
同一份数据,在每一层有不同的名字
--------------------------------------------------------------------
**「通过对话理解分层」讲的是「各管一段」;在数据上看到的是「各叫一个名字」。**
层 英文名 典型称呼
--------------------------------------------------------------------
应用层 报文(message) HTTP 请求/应答
传输层 段(segment)/数据报(datagram) TCP 段/UDP 数据报
网络层 包(packet) IP 包
链路层 帧(frame) 以太网帧
物理层 比特(bit) 电/光信号
**这五个名字不是修辞,是排障时的坐标**:
**说「丢包」指网络层,说「丢帧」指链路层,说「超时」多半在传输层。**
**分层的代价是什么**:
**每一层都要剥头、查错、再上交,一层套一层就多一次拷贝。**
**所以高性能场景会出现「旁路」「零拷贝」这些词**——**本质都是想把中间几层省掉。**
同一个 hello world,在四层里长度分别是 11、31、51、65:每下一层就多 20 或 14 字节。
物理层那一列是比特数,不是字节数:65 字节乘 8 等于 520 个比特。
这一层没有「报文」的概念,只有连续的信号。
注意 segment 那一行的 31 用的是 20 字节 TCP 头:
如果换成 UDP,头只要 8 字节,这一行就变成 19——这就是「段」与「数据报」在长度上的直接差别。
30 秒实验
- 把
tcp4h换成udp4h,看四层的长度各变多少。 - 算一下:如果只发 1 个字节的数据,头和数据的比例是多少?这解释了为什么「心跳包」要尽量小。
- 想一个你遇到过的「网络通但内容不对」的例子,判断它落在哪一层。
常见误区
- 以为报文、段、包、帧是同义词。 它们各指一层:说错层,查错方向。
- 以为 TCP 段与 UDP 数据报只是叫法不同。 它们性质不同:TCP 是字节流切出来的段, UDP 是独立的数据报。
- 以为「网卡了」是同一个问题。 丢包、丢帧、超时、乱码分属四层,工具和负责人都不同。
自测三问(点开对答案)
1. 「丢包」与「丢帧」分别指哪一层的问题? —— **丢包指网络层(IP 包),丢帧指链路层(以太网帧)。**前者查路由与分片,后者查网线、双工、 CRC 错。 2. 为什么说「乱码」最能体现分层的价值? —— **因为网络全程通、字节一个不差,错在最上面的编码声明。**有分层概念, 才能把「通不通」与「懂不懂」分开判断。 3. OSI 有「表示层」,TCP/IP 没有,后果是什么? —— **编码转换交给应用自己做**,于是每个应用各自发明 `charset`、`Content-Encoding`, 同一个问题被解决了几十遍。下一节给出正式的名字:OSI 七层参考模型。
- ☐ (本节完,下一节 1.5.3 OSI参考模型)