📚 第一章 网络基础知识
📄 一句话概括

分层的比方:经理交代一件事,要经过翻译、秘书、收发室,每层各包一层。 每层给这份数据起一个新名字——名字就是排障时的坐标。

📝 本节和前面几节的关系

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 秒实验

  1. 把 tcp4h 换成 udp4h,看四层的长度各变多少。
  2. 算一下:如果只发 1 个字节的数据,头和数据的比例是多少?这解释了为什么「心跳包」要尽量小。
  3. 想一个你遇到过的「网络通但内容不对」的例子,判断它落在哪一层。

常见误区

  1. 以为报文、段、包、帧是同义词。 它们各指一层:说错层,查错方向。
  2. 以为 TCP 段与 UDP 数据报只是叫法不同。 它们性质不同:TCP 是字节流切出来的段, UDP 是独立的数据报。
  3. 以为「网卡了」是同一个问题。 丢包、丢帧、超时、乱码分属四层,工具和负责人都不同。
自测三问(点开对答案) 1. 「丢包」与「丢帧」分别指哪一层的问题? —— **丢包指网络层(IP 包),丢帧指链路层(以太网帧)。**前者查路由与分片,后者查网线、双工、 CRC 错。 2. 为什么说「乱码」最能体现分层的价值? —— **因为网络全程通、字节一个不差,错在最上面的编码声明。**有分层概念, 才能把「通不通」与「懂不懂」分开判断。 3. OSI 有「表示层」,TCP/IP 没有,后果是什么? —— **编码转换交给应用自己做**,于是每个应用各自发明 `charset`、`Content-Encoding`, 同一个问题被解决了几十遍。

下一节给出正式的名字:OSI 七层参考模型。

相关笔记