网络知识总库

Book Notes · 02 / 14 · 核心教材

计算机网络:系统方法
精读笔记

Peterson 与 Davie 不把网络写成协议词典,而写成一套可以替换零件的系统。 每一章都在问:功能放在哪一层、状态放在端还是放在网、资源是统计复用还是预约。 第 6 版把这条设计权衡的主线从直连链路一路拉到拥塞、安全与应用。 本笔记按八块原创转述,并指向免费在线版。

作者 Larry L. Peterson / Bruce S. Davie 难度 系统设计向 建议用时 约三周 笔记形式 设计权衡精读

全书骨架:先定需求,再谈权衡

系统方法的读法不是「下一章又是哪个协议」,而是「上一章留下的需求,这一章用哪种代价去兑现」。 原书九章在此合并为八块:把端到端数据与安全收成一章,好让「保护什么、在哪一层保护」跟表示与压缩放在同一张权衡表上。

① 需求与架构→ ② 直连链路→ ③ 互联与路由→ ④ BGP / MPLS→ ⑤ UDP / TCP→ ⑥ 拥塞与 QoS→ ⑦ 数据与安全→ ⑧ 应用与叠层
FIG.0 — 从问题陈述走到应用:每一跳都在重谈「谁来负责」
三条需求

连通、经济地共享资源、支撑通用服务。后面所有机制都可以回溯到这三条里的一条或一条以上。

分层是工具不是教条

协议、封装、多路复用是管理复杂度的手段。功能放错层,正确性或性能会先坏掉。

端到端论点

只有端系统才看得到的正确性,不要幻想在网络中间「顺便做完」。中间层可以优化,不能替代。

性能先看乘积

带宽、时延各自有用,真正决定窗口和流水线的是时延带宽积。很多「算法很差」其实是管道没填满。

01

基础与设计方法 —— 先问系统要什么

开篇不急着介绍某族协议,而是把网络定义成「用链路和交换机把节点连起来的系统」, 再列出它必须满足的需求。后面七章都是这些需求的实现菜单。

连通、共享与通用服务

连通不只是两台主机有一条线,而是任意一对进程最终能交换数据。 规模一大,直接全互联不可能,必须引入交换,让链路被许多对话分时使用。

经济地共享资源,靠的是统计复用:突发流量叠加之后,平均负荷远低于峰值之和。 代价是队列、丢失和不可预测的时延。若改用电路式预约,时延变稳,利用率通常下降。

通用服务要求网络不要为每一种应用定制一张专网。 于是出现协议:对等实体就报文格式和时序达成契约,上层靠下层的服务模型组合出自己的语义。

连通用交换把点对点链路扩展成任意到任意 共享统计复用换利用率,预约换可预期 服务用协议接口让应用复用同一张网 代价队列、丢失、复杂度和失败模式

架构:层、协议与封装

分层把问题切成可替换的模块。每一层向其上一层提供服务,向其对等层说话。 封装是这种说话方式的物理形态:本层控制信息贴在载荷前面,到了对等层再被读走。

权衡立刻出现。层数多,演化容易、实现可替换;层数少,路径上的重复工作和头部开销更少。 「可靠传输放在哪」是全书反复出现的例子:链路层做一次,能挡住随机误码; 端到端再做一次,才能对付路径中段的丢失和中间盒。两边都做会重复,只做一边会漏。

应用数据→ 运输头→ 网络头→ 链路头→ 比特上线
FIG.1 — 封装是设计决策的痕迹:每多一个头,就多一个「谁负责」

性能:带宽、时延与管道

带宽描述单位时间能推进多少比特,时延描述一个比特或一个报文要走多久。 往返时延决定控制回路有多慢;时延带宽积决定「管道里能装多少未确认数据」。

抖动是时延的变化,实时应用比文件传输更在乎它。 系统方法强调:先算出管道有多粗、有多长,再谈窗口、缓冲和拥塞算法,否则会把容量问题误诊成实现 bug。

易混淆:「网络很慢」至少要拆成低吞吐和高时延两种病。 前者看瓶颈带宽和是否填满管道,后者看距离、排队和握手次数。 用同一个「加速」去治两种病,设计会走偏。
02

直连网络 —— 一跳上的五个子问题

在讨论互联网之前,先把「一根链路两端如何可靠对话」拆开。 编码、成帧、检错、可靠传输、多路访问,每一个都是独立的设计点。

从比特到帧

节点和链路是硬件积木。链路上先要约定比特怎么变成信号:这是编码的工作。 编码既要能恢复时钟,又要限制连续相同符号,还要在实现成本和频谱效率之间折中。

成帧回答「一串比特从哪开始、到哪结束」。 定界符需要在数据里转义,长度字段则把信任交给那个数字本身。 两种方案对差错的敏感点不同:定界符怕伪装,长度字段怕长度本身被改坏。

编码→ 成帧→ 检错→ 可靠传输→ 多路访问
FIG.2 — 直连链路上的问题栈:上一层总以下一层「够好」为前提

检错与一跳可靠

检错用冗余发现比特翻转。循环冗余校验把帧看成多项式,用约定的生成式去除,余数随帧发送。 它比简单奇偶强得多,但仍是检错,不是自动恢复。

一跳可靠传输把确认、序号和定时器请回来。 停等实现简单,管道利用率低;滑动窗口用序号空间换吞吐。 关键权衡是:链路层要不要做可靠。 误码高、往返短的链路值得做;已经很干净的光纤上,把恢复留给端到端往往更划算。

共享介质:以太网与无线

多路访问是「谁先说话」的协议。信道划分稳定但浪费空闲槽;随机访问灵活但有冲突;轮转公平但有轮询开销。 经典以太网选择载波侦听加冲突检测,后来用交换机把共享介质拆成点对点全双工,冲突从设计中心退成历史注释。

无线把同一组问题置于不能边发边听、还有隐藏终端的环境里,于是冲突避免、短控制帧预约和自适应速率成为默认菜单。 直连章的 eth / wifi 案例不是要你背帧格式,而是演示:介质变了,上面那五个子问题的最优解就一起变。

易混淆:链路层可靠和端到端可靠不是互斥选项里的单选题。 链路层挡的是一跳随机误码,端到端挡的是整条路径上的丢失、失序和中间设备丢弃。 只做一边,会在另一边的故障模式下露馅。
03

网络互联 —— 把异构链路拼成一张网

直连只能覆盖一跳。互联章回答:不同技术、不同管理域的网络,怎样对外呈现出统一的分组投递服务。 核心权衡是数据报还是虚电路,以及状态放在网络里还是放在端上。

交换:数据报对虚电路

数据报网络让每个分组自带目的地址,路由器独立查表转发,网络几乎不保存每条会话的状态。 好处是鲁棒、易绕开故障;坏处是无法在中间保证每分组走同一条路,也更难做精细的资源预约。

虚电路先信令后数据,交换机记住连接标识。 好处是转发查短标签、便于预约;坏处是信令复杂、故障要重建状态。 因特网选了数据报作为默认,不等于虚电路思想消失——后面的 MPLS 会把它以另一种形态请回来。

数据报无连接;状态在端;按地址转发 虚电路先建路;状态在网;按标签转发 网桥在链路上学习扩展局域网,不改网络层 路由器在网络层终结链路,改写下一跳

IP 作为统一的薄腰

互联成功的关键是找到一个足够窄的公共层:上面可以长出许多运输与应用,下面可以接许多链路。 IP 扮演这个细腰。它提供尽力而为的主机到主机数据报,不保证不丢、不乱序、不重复。

编址从分类走到无类别前缀,子网让一块地址服务一条链路,DHCP 把配置从手工里解放出来。 ARP 在「已知下一跳 IP、未知本跳 MAC」时补上最后一块。 ICMP 把不可达、超时等控制信息送回源。 这些辅助协议都是为了让细腰保持薄:主协议不背所有杂务。

异构链路→ IP 细腰→ 统一数据报→ 多种运输 / 应用
FIG.3 — 沙漏腰:多样性被压到上下两端,中间刻意保持简单

路由:分布式算路

转发表不会自己长出来。距离向量跟邻居交换开销向量,实现简单,收敛慢,有计数到无穷。 链路状态洪泛邻接信息,各节点独立算最短路,收敛快,但要维护全网视图。

度量选择本身就是权衡:跳数实现容易,却无视带宽;容量或管理员代价更贴近工程,却可能振荡。 域内路由假设目标函数大体一致,这才允许「最短」二字成立。一出管理域,这句话就不成立了。

易混淆:网桥把局域网变大,路由器把网络隔开。 用网桥无限扩展广播域,看起来省事,广播、故障域和学习表都会一起膨胀。 互联的默认工具是路由器,网桥是「同一链路技术内部的扩展」。
04

高级互联 —— 全球、移动、标签与集中控制

基本 IP 只能处理「一个管理域里的尽力而为」。 走出域、支持新地址、做组播、做流量工程,都要在细腰两侧加机制,并且每次都重新谈判状态放在哪。

BGP:策略代替最短路

自治系统之间交换的不是「哪条路跳数最少」,而是「我愿意让你怎么用我的网络」。 BGP 用路径向量携带经过的 AS 列表来破环,用一串属性表达偏好。

设计权衡非常清楚:放弃全局最优,换来各域自治。 代价是路径可能绕远、收敛可能慢、错误宣告可以快速传遍全球。 读 BGP 时把商业关系(客户、对等、提供者)画出来,比背属性名字有用。

IPv6 与组播

IPv6 用更长的地址和更干净的固定头,把分片赶回源端,用邻居发现替换 ARP 的部分职责。 它证明:即使细腰要换代,也必须保持「薄」——复杂度尽量进扩展头和端系统。

组播把「一源多目的」从多次单播里解放出来,但要在树上维护状态。 状态在网络里,效率高、管理难;状态在端上(应用层组播),部署易、链路会重复传。 许多应用最终选了后者,不是因为组播理论错了,而是运维权衡输了。

域内最短路→ 域间策略→ IPv6 细腰 2.0→ 组播树→ MPLS 标签
FIG.4 — 高级互联:每一次扩展都在问要不要往网络里再塞一点状态

MPLS 与集中式控制

MPLS 在入口给分组贴标签,中间只按标签交换,出口再剥掉。 它把虚电路的转发效率请回数据报网络,却不必让主机改协议栈。 流量工程、VPN、快速重路由因此变得好做——网络重新持有每条「伪电路」的状态。

软件定义网络把权衡再推进一步:数据平面留下匹配—动作,控制平面逻辑集中。 全局视图让策略好写,控制器的可用性、控制时延和流表容量变成新的系统问题。 系统方法在这里最典型:不是「集中一定更先进」,而是「你把哪类复杂性搬到了哪」。

易混淆:MPLS 标签不是另一种 IP 地址。 地址标识端点,标签标识一条被网络承认的转发等价类。 把 MPLS 理解成「更快的路由查找」只对了一半,另一半是控制平面愿意为这条类维护状态。
05

端到端协议 —— 进程之间究竟要什么服务

网络层只把数据报送到主机。端到端协议决定进程看到的是数据报、字节流、远程调用还是实时帧。 选择哪种服务,就是在简单性、可靠性、时延和实现位置之间做买卖。

UDP:细腰之上最薄的一层

UDP 几乎只做复用:端口加上可选校验。 它保留报文边界,不建立连接,把丢失和失序如实交给应用。 当应用自己有时效性或自己想做重传策略时,这层薄是优点而不是缺陷。

TCP:可靠字节流的代价

TCP 把数据报通道加成面向连接的可靠字节流。 握手交换序号,滑动窗口填满时延带宽积,累计确认加超时完成恢复,接收窗口保护对端缓存。

代价写在设计里:没有应用报文边界;短事务要付握手和慢启动的税; 把拥塞控制绑在同一个协议里,使「可靠」和「对网络友好」成为捆绑销售。 后来的演进(选择确认、更现代的窗口增长、用户态实现)都是在不拆掉字节流合同的前提下改内部算法。

UDP 数据报/ TCP 字节流/ RPC 调用/ RTP 实时帧
FIG.5 — 四种端到端合同:可靠、时延、消息边界,三者很难同时最优

RPC 与实时运输

远程过程调用想让跨机器像本地调用。 它必须处理部分失败:请求丢了、应答丢了、被调用方崩溃,本地调用里不存在的语义都会冒出来。 「至少一次」还是「至多一次」,是接口设计而不是传输细节。

实时应用常选带时间戳和序列号的数据报轮廓(RTP 一类),把丢失交给编解码器而不是重传。 端到端论点在此再次出场:中间网络无法知道哪一帧对人耳更重要,应用可以。

易混淆:TCP 的「连接」容易被理解成网络里真有一条管子。 管子只存在于两端的控制块。路径上仍然是无连接数据报。 因此中间链路翻动时,TCP 可能只是暂时降窗,也可能因为地址变了而彻底断掉——那是标识变了,不是管子被剪断。
06

拥塞控制与资源分配 —— 谁该慢下来

统计复用省下了电路的浪费,账单是拥塞。 这一章问:队列怎么排,信号怎么回,公平怎么定义,要不要为某些流预约。

分配问题与排队规则

资源分配可以在端上做、在路由器上做,或两边一起做。 先到先服务实现简单,不能隔离恶邻;公平排队按流切蛋糕,隔离好,状态和调度更贵。

主动队列管理在队列溢出前就丢或标记,好让端系统早点减速,避免锁步振荡。 标记比丢弃更温和,但要端系统认识这种显式信号。 权衡仍是:网络愿意维护多少每流状态,换取多少可预期性。

端上控制根据丢包或时延估计容量;网络保持简单 网内排队决定谁先出、谁被丢、谁被标记 预约 / QoS用信令和分类换可预期时延 信号隐式(丢、时延)或显式(标记)

TCP 拥塞控制作为分布式算法

经典 TCP 把拥塞窗口当作对路径容量的估计:慢启动探测,线性增加挤占,丢包后乘性回退。 它不需要路由器告诉它「你该是多少」,这是因特网能扩张的重要原因。

缺陷同样清楚:把丢包当成拥塞信号,在无线误码和换路上会误判; 填满深缓冲会把时延堆高;短流还没进入稳态就结束。 后续算法改窗口增长曲线、改用时延或带宽测量,都是在同一分配问题里换传感器,不是换问题。

慢启动→ 拥塞避免→ 丢 / 标记→ 乘性减→ 重新探测
FIG.6 — 端到端拥塞控制:一条没有中央调度员的反馈回路

服务质量:预约值不值

若交互语音不能容忍排队的长尾巴,可以给它分类、限速、预约。 综合服务走每流预约,精细但难扩展;区分服务走聚合类,扩展好但保证变软。

系统方法的结论通常很克制:多数应用靠弹性拥塞控制就够; 真要硬保证,就必须让网络重新持有状态,并回答谁来买单。 「全部流量都要 QoS」往往只是还没算过状态和策略成本。

易混淆:加大缓冲能提高链路利用率,也会把时延变成应用可感知的卡顿。 缓冲不是越大越安全。拥塞控制要的是「刚刚好填满管道」的队列,不是「能吞下一整段拥塞周期」的水库。
07

端到端数据与安全 —— 比特的含义和信任

运输层交出的是字节。应用还要约定这些字节怎么解释,要不要压缩,以及路上的人能不能看、能不能改。 原书分两章的内容,这里按同一条权衡线合并:功能仍然放在端上,除非密钥分发或性能逼你另想办法。

表示、编码与压缩

不同机器的整数端序、浮点格式、字符集都不一样。 表示层的工作是约定一种规范形式,或约定「跟发送方走」再带上自描述。 自描述灵活、费带宽;规范形式紧凑、演化要改契约。

压缩把冗余换成 CPU。无损压缩保住每一个比特,有损压缩丢掉人觉得不重要的信息。 实时媒体几乎总是有损加适配码率——这是应用比网络更懂「什么可以丢」的又一例。

密码学积木放在哪一层

机密性、完整性、认证可以贴在应用、运输之上、网络或链路上。 贴得越高,越接近真正的端到端;贴得越低,对应用越透明,也越容易在中间被合法终止。

对称密码快,非对称密码解决密钥分发和签名。 实用协议几乎总是用非对称完成认证与密钥协商,再用对称保护数据。 端到端论点在安全里变成:中间盒若解密再加密,它就必须进入信任边界。

应用内保护/ 运输上的 TLS/ 网络层 IPsec/ 链路加密
FIG.7 — 保护点下移则透明,上移则更端到端;没有免费的「全透明且全信任」

认证、密钥与常见系统

认证协议要防重放,通常靠一次性随机数。 公钥证书把身份和公钥绑在一起,信任锚仍要预置。 邮件可以在应用里签名加密,Web 把 TLS 衬在 HTTP 下面,站点互联常用网络层隧道。

这些不是三套互相替代的产品,而是三种信任范围。 选错层会出现「接入网加密了,代理仍能读正文」或「隧道很安全,但用户到隧道口仍是明文」。

易混淆:压缩和加密的顺序不能随便调。 先加密再压缩,密文接近随机,压缩几乎失效;先压缩再加密,才是常见顺序。 安全协议若处理不当,还可能用压缩泄露侧信息。细节属于实现,顺序属于设计。
08

应用 —— 协议栈存在的理由回到地面

应用章不是附录。传统应用演示请求/响应和客户—服务器,多媒体演示时延敏感, 基础设施应用(目录、覆盖、分发)演示「用应用层再做一次网络」。

传统应用:邮件、Web、DNS

邮件把投递和读取拆开,服务器之间推送,用户再拉取。 Web 把对象命名在 URL 里,用无状态请求换可缓存性。 DNS 用层次加缓存把名字变成地址,自己也变成许多系统的控制面。

三者都说明:应用协议可以很简单,一旦加上垃圾邮件、缓存一致、缓存投毒,复杂度会回到运维和信任,而不是回到报文格式。

SMTP服务器间推送信件;读取另走协议 HTTP无状态对象传输;会话由应用外挂 DNS分层目录;缓存决定真实查询量 管理配置与遥测也是应用,只是用户是运营商

多媒体与自适应

连续媒体把时延和抖动抬到比可靠更优先的位置。 播放器靠缓冲吸收抖动,靠切换码率吸收吞吐变化。 网络若只提供弹性尽力而为,应用就必须自己闭合这条控制回路。

覆盖网:在 IP 之上再做一次互联

CDN、对等分发、应用层组播,都是在主机之间再铺一张逻辑网。 它们能绕开 IP 组播难部署、能按应用度量选路、能把缓存放到离用户近的地方。

代价是重复:覆盖网自己要发现节点、维护路由、处理抖动。 系统方法把它看作正当的分层——当细腰不愿意加某种状态,应用层会把状态捡起来。 读到这里应能回头解释全书:不是「应用很高级所以放在最上面」,而是「分不到下层的需求,最终由应用自己实现」。

传统客户—服务器→ 媒体自适应→ 目录 / DNS→ 覆盖与 CDN
FIG.8 — 应用层会把网络层拒绝持有的状态重新实现一遍
全书收束:合上书只记协议名,等于没读。 应当能对任一机制回答四问:它满足哪条需求、状态在端还是在网、牺牲了什么、若把功能上移或下移一层会怎样。 答得出,系统方法就读通了。

读后自测 · 8 题

1. 统计复用省下了什么,账单是什么?
它让突发用户共享链路,避免按峰值预约造成的空闲浪费。账单是排队、丢失和时延不可预测。若应用要硬保证,就得把一部分资源重新预约回去,也就是部分退回电路思维。
2. 端到端论点并不禁止链路层做可靠传输。这句话对吗?
对。论点反对的是「只在中间做、端上不做」的幻想:端到端正确性只能由端来确认。链路层重传仍可作为性能优化,挡住一跳误码、减少端到端恢复。优化不能替代端上的最终检查。
3. 为什么时延带宽积比单独谈带宽更重要?
它告诉你管道里能装多少未确认数据。窗口小于这个乘积,链路就会空转。许多「协议很慢」其实是发送方不敢或不能把管道填满,而不是链路标称速率不够。
4. 数据报和虚电路各自把状态放在哪?MPLS 站哪边?
数据报让分组自带地址,网络少保存每会话状态;虚电路让网络记住连接。MPLS 在数据报世界里重新引入标签转发和网络侧状态,主机可以继续只看见 IP。
5. BGP 为什么不追求最短路?
域间的目标函数是策略和商业关系,不是统一度量下的最短。路径向量和属性用来表达「愿意怎么连」,不是用来逼近全局 Dijkstra。把 BGP 当互联网版 OSPF,会把一次策略选择误判成算路错误。
6. 为什么许多应用最终没用 IP 组播,而用覆盖网?
IP 组播要在网络里维护树和状态,跨域部署和计费都难。覆盖网把复制和选路搬到端上,重复消耗一些带宽,换来可部署性。这是「状态放在哪」的典型工程结论,不是组播算法失效。
7. 加大路由器缓冲一定能改善拥塞吗?
不一定。更大的缓冲能提高利用率、吸收突发,也会堆高时延,让交互应用变钝。主动队列管理的动机之一,就是避免用无底水库把反馈拖得太迟。
8. 安全功能上移或下移一层,各得到什么、失去什么?
上移(应用内或 TLS)更接近真正的端到端,中间盒看不懂,应用或库要配合。下移(IPsec、链路加密)对应用透明,也更容易在边界被合法终止。信任边界跟保护点必须画在一起,否则会误以为「已经加密」等于「对手看不见」。