NET-05 传输层
05 · 传输层(Transport Layer)
📅 预计 90 分钟 | ⭐ 本章主题:进程间的"端到端"通信,可靠传输的整套机制
5.0 先给直觉:传输层是"快递公司的接单客服"
网络层负责把数据从"城市 A"送到"城市 C"。但送到之后呢?数据到达的是一台主机,而主机上同时开着很多程序:浏览器、微信、邮件、网课……数据该交给哪个程序?
传输层就是解决这个问题的——它像快递公司的客服:
- 每一份数据都标了"收件人分机号"(端口号),客服知道该转给哪个部门(进程)。
- UDP 客服:不管件到没到、坏没坏,扔出去就不管了(快但不保证)。
- TCP 客服:登记、确认、丢件重发、控制流量,务必"一件不少、顺序不乱"(慢但可靠)。
传输层是整个网络的**"最后一公里配送"**,提供两个重要能力:端口寻址(给进程) 和 可靠传输(TCP)。
5.1 端口号:给进程的分机号 ⭐⭐
数据到了主机,怎么找到"具体程序"?
IP 地址找到主机,端口号(port) 找到主机上的具体进程。IP + 端口合起来叫套接字(socket),是"主机 + 进程"的唯一标识。
一次 TCP 连接由四元组唯一确定:
(源 IP,源端口,目的 IP,目的端口)
例:访问百度首页
源:192.168.1.5:54321 → 目的:110.242.68.66:80
端口号范围:0 ~ 65535(16 位)。常见的几个要背:
| 端口 | 服务 | 端口 | 服务 |
|---|---|---|---|
| 21 | FTP(文件传输控制) | 53 | DNS(域名解析) |
| 22 | SSH(远程登录) | 80 | HTTP(网页) |
| 25 | SMTP(发邮件) | 443 | HTTPS(加密网页) |
💡 记忆口诀:"80 网页、443 加密网页、53 DNS、21 FTP、22 SSH"。记这几个高频的,其他见到查表即可。
⚠️ 常见错误
- 把端口和 IP 混为一谈:IP 找主机,端口找进程,两个都必需。
- 把 53 记成 HTTP:53 是 DNS(域名解析);80/443 才是网页。
- 四元组记不齐:完整标识一条连接要"源 IP、源端口、目的 IP、目的端口"四项,缺一项就可能张冠李戴。
5.2 UDP:轻量级"只管送" ⭐⭐⭐
寄平信,不挂号
UDP(User Datagram Protocol,用户数据报协议) 是无连接、不可靠的传输协议。像寄平信:写好地址就投进邮筒,不确认收到、不保证顺序、不保证不丢。
特点:
- 无连接:发之前不用"握手",直接发。
- 不可靠:不确认、不重传、不保证顺序。
- 首部小(8 字节),开销低。
- 支持一对多/一对全:适合广播和组播。
UDP 报文段结构(首部就 4 个字段):
| 源端口(16) | 目的端口(16) |
| 长度(16) | 校验和(16) |
| 数据... |
适合用 UDP 的场景:实时性优先、可以容忍少量丢失——视频直播、语音通话(丢一帧画面没事,卡顿才难受)、DNS 查询、DHCP。
💡 一句话:UDP = 平信:快、省、不管到没到。适合"宁可少一点也不能慢"的应用。
⚠️ 常见错误
- 以为 UDP 一定比 TCP"坏":UDP 在实时场景(视频/语音)是更好的选择,"不可靠"是特性不是缺陷。
- 把 UDP 首部记成 20 字节:TCP 首部一般 20 字节,UDP 首部只有 8 字节。
- 以为 UDP 能做广播:TCP 是点对点的连接,做不了广播;UDP 可以广播/组播。
5.3 TCP 报文段:可靠传输的"包裹单" ⭐⭐
TCP(Transmission Control Protocol,传输控制协议) 是面向连接、可靠、按字节流的传输协议。像寄挂号信:编号、签收、丢件补发。
TCP 报文段首部(标准 20 字节)关键字段:
| 源端口(16) | 目的端口(16) |
| 序号 sequence(32) |
| 确认号 ack(32) |
| ... | 标志位(URG ACK PSH RST SYN FIN) | 窗口大小 |
| 校验和(16) | 紧急指针(16) |
| 数据... |
关键字段含义:
- 序号(seq):本报文段数据第一个字节的字节号(TCP 是字节流,按字节编号)。
- 确认号(ack):期望收到对方下一个字节的序号,等于"对方已经收到 ack−1 之前的所有字节"。
- 标志位:
- SYN:请求建立连接(握手用)。
- ACK:确认号有效(几乎每个包都带)。
- FIN:请求关闭连接(挥手用)。
- RST:异常重置连接。
- PSH:立即交付应用层。
- 窗口大小:告诉对方"我的接收缓冲区还能收多少",是流量控制的依据。
💡 记忆口诀:"序号数第一个字节,确认号是期待下一个,SYN 建连、FIN 断开"。
⚠️ 常见错误
- 把序号当"第几个包":序号是字节号不是包号——一个包可能带 1460 字节数据,下一个包序号跳着走。
- 确认号含义记反:确认号 ack = "我期待你下一个字节的号",代表它之前的都已收到。
- 首部长度记混:TCP 标准首部 20 字节,UDP 8 字节。
5.4 三次握手:建立连接 ⭐⭐⭐
通话前先对好暗号
TCP 是面向连接的,通信前必须先建立连接。三次握手(three-way handshake)的过程:
客户端 C 服务器 S
| |
|── SYN=1, seq=x ────────────────▶| ① C 说:我要连你(SYN,带上我的初始序号 x)
| |
|◀── SYN=1, ACK=1, seq=y, ack=x+1 ─| ② S 说:收到,我也要连你(SYN+ACK,带上我的初始序号 y,确认 x)
| |
|── ACK=1, seq=x+1, ack=y+1 ────▶| ③ C 说:确认收到你的 y(ACK)
| |
|◀════ 连接建立,开始传数据 ════▶|
为什么是三次不是两次?——第二次的 SYN 和 ACK 要分清楚职责:① 让服务器确认"客户端能发";② 让客户端确认"服务器能收能发";③ 让服务器确认"客户端能收"。如果只两次,服务器无法确认"客户端收到了我的 SYN",可能造成半连接(服务器以为连上了,客户端其实没收到)。
💡 记忆口诀:"三次握手:问→应→确认"。第一次问,第二次应并回问,第三次确认。核心是让双方都确认"你能收到我的话"。
⚠️ 常见错误
- 把第三次握手省掉:第三次 ACK 缺了,连接建立不完整(服务器认为建立,客户端可能没收到,浪费服务器资源——这就是 SYN 洪泛攻击的原理)。
- 第二次为什么同时带 SYN 和 ACK:因为 TCP 连接是双向的,服务器也要建立自己的连接方向,把应答和请求合并在一个包里。
- 握手之后才传数据:三次握手完成前不会传应用数据,第三次握手包可以顺带带数据(但在教学考试里一般说第三次起才开始传)。
5.5 四次挥手:释放连接 ⭐⭐⭐
各说各的再见
TCP 是全双工,两条方向的连接独立关闭,所以要四次挥手(four-way handshake):
客户端 C 服务器 S
| |
|── FIN=1, seq=u ──────────────────▶| ① C 说:我不再发了(关闭我的发送方向)
| |
|◀── ACK=1, ack=u+1 ────────────────| ② S 说:收到(但 S 可能还有数据要发)
| |
|◀── FIN=1, seq=w ──────────────────| ③ S 说:我的数据发完了,我也要关(关闭它的发送方向)
| |
|── ACK=1, ack=w+1 ────────────────▶| ④ C 说:收到,关闭
几个要点:
- 为什么 ③ 不能和 ② 合并:因为服务器收到 FIN 后,可能还有数据要发,所以先只确认(②),等数据发完再发 FIN(③)。这中间的时间差导致多一次挥手。
- TIME_WAIT:客户端发完第四次 ACK 后要等 2MSL(两倍最大报文段寿命),确保最后的 ACK 能被服务器收到、旧连接的数据在网络上彻底消失,防止影响新连接。
- 为什么需要四次:每个方向的"关闭"都需要一次"请求 FIN + 一次确认 ACK",两个方向共四次。
💡 记忆口诀:"挥手四次:我关→你确认→你关→我确认"。全双工两条路,各走各的流程。
⚠️ 常见错误
- 为什么不是三次:因为服务器可能还有数据要发,不能和 ② 一起关。数据发完才发 FIN。
- TIME_WAIT 是在谁身上:主动关闭方(先发 FIN 的一方)在发完最后 ACK 后进入 TIME_WAIT,等待 2MSL。
- 挥手和握手的包都混了:握手用 SYN 开头,挥手用 FIN 开头;握手 3 包、挥手 4 包。
5.6 可靠传输:确认、序号、重传 ⭐⭐⭐
挂号信的三件套
TCP 怎么保证"数据不丢、不乱"?靠三件套:
- 序号(sequence number):给每个字节编号,接收方按序号重排,乱序也能恢复。
- 确认(acknowledgment):接收方告诉发送方"我收到哪了"。
- 重传(retransmission):超时没收到确认 → 发送方重发。
机制细节:
- 确认与重传(ARQ):发送方发出数据后启动重传计时器,若在超时时间内没收到 ACK,就认为丢了,重新发送。
- 累积确认:TCP 的确认是"累积"的——确认号 ack=n 表示"n−1 及以前的所有字节都收到了",不用对每个包单独确认。
- 快速重传:如果连续收到 3 个重复的 ACK,说明中间丢了包,发送方不等超时立即重传(更快)。
A 发 seq=1..100, 101..200, 201..300
但 101..200 丢了
B 收到 1..100 → 发 ACK=101(期望 101)
B 收到 201..300 → 发现缺 101..200,仍发 ACK=101(重复确认)
A 连收 3 个重复 ACK=101 → 不等超时,立即重传 101..200(快速重传)
💡 记忆口诀:"序号防乱序,确认报进度,超时或三个重复 ACK 就重传"。
⚠️ 常见错误
- 超时重传 vs 快速重传分不清:超时重传是"等计时器到点";快速重传是"收到 3 个重复 ACK 立即发",更快。
- 累积确认不是"每个包单独回一个":ack=n 覆盖 n−1 之前所有字节,能减少确认包数量。
- 确认号是"期望的下一个序号"不是"已收到的最后一个序号":
ack=x+1表示已收到 x,期待 x+1。
5.7 滑动窗口与流量控制 ⭐⭐⭐
收件箱放不下了,请"慢点发"
接收方缓冲区是有限的。如果发送方不管不顾猛发,接收方缓冲区会溢出丢包。流量控制(flow control) 就是"让发送方的发送速度适配接收方的接收能力"。
实现机制:滑动窗口 + 窗口通告。
- 接收方在 ACK 里带一个**窗口(window)**字段,告诉发送方"我这还能再收多少字节"。
- 发送方维护一个发送窗口:窗口内的字节已发但未确认,可以继续发;窗口满了就停,等 ACK 把窗口"前移"。
发送窗口(大小 4 个字节序号):
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
↑已确认 ↑←←窗口内(可发/已发)→→↑ ←未发,等窗口前移
收到对 1、2 的确认 → 窗口右移两格,可继续发 5、6
- 滑动窗口 VS 停等协议:最早的协议"发一个等一个"(停等),效率极低;滑动窗口允许连续发多个再等确认,充分利用带宽。
- 窗口大小 = min(接收方通告窗口, 拥塞窗口)——流量控制管"接收方能力",拥塞控制管"网络能力",两个都满足才发。
💡 记忆口诀:"窗口=还没被确认但可以发的额度,收据(ACK)一来窗口就往前滑"。
⚠️ 常见错误
- 把流量控制和拥塞控制混了:流量控制管"接收方缓冲区装不下"(端到端、靠窗口通告);拥塞控制管"网络堵了"(靠拥塞窗口、慢启动等)。前者治"下游收不动",后者治"路上堵车"。
- 窗口是"字节数"不是"包数":滑动窗口以字节(序号)为单位。
- 以为窗口固定不变:窗口随 ACK 动态滑动,接收方还能随时通告更小的窗口来压速度(甚至通告 0 停止发送)。
5.8 拥塞控制 ⭐⭐
路上堵车了,别一股脑往里挤
拥塞控制(congestion control) 处理的是"网络中间堵了"——路由器的队列满了、大量包被丢弃。发送方要"收敛"自己的发送速率。
四种机制(阶段),记忆按顺序:
- 慢启动(slow start):拥塞窗口从 1 开始,每收到一个 ACK 窗口翻倍(指数增长)。不是真的"慢",是从小到大探路。
- 拥塞避免(congestion avoidance):窗口涨到慢启动阈值(ssthresh)后,改为线性加一(每个往返周期 +1),缓慢增长。
- 快重传(fast retransmit):收到 3 个重复 ACK → 立即重传丢失的报文。
- 快恢复(fast recovery):把 ssthresh 降为当前窗口的一半,窗口也从半值继续线性增长。
窗口大小
↑
| ← 慢启动(指数增)
| ← 到阈值 → 拥塞避免(线性增)
| ↓ 发生丢包(3 个重复 ACK 或超时)
| ← 快恢复:ssthresh 减半,窗口减半,再线性爬
+──────────────────→ 时间
💡 记忆口诀:"慢启动指数探路,拥塞避免线性爬,丢包减半再恢复"。记住"快"字辈的两个动作都发生在丢包时。
⚠️ 常见错误
- 慢启动不是"慢慢发":它是指数增长快速试探,"慢"指从很小(1 个报文段)起步。
- 流量控制 vs 拥塞控制的触发对象:流量控制看接收方的窗口通告;拥塞控制看网络的丢包/拥塞信号。
- 快恢复和快重传是一对:收到 3 个重复 ACK 时"快重传"丢的包,同时"快恢复"把阈值和窗口减半,不是降到 0 重来(只有超时才从慢启动重新开始)。
5.9 TCP 的连接状态:连接是有"生命周期"的 ⭐
建立、使用、关闭,每一步都有名字
TCP 连接不是一个瞬间动作,而是一个状态机——从创建到关闭,连接处于不同的状态。记住几个高频状态:
| 状态 | 出现在 | 含义 |
|---|---|---|
| LISTEN | 服务器 | 服务器在监听,等待连接请求 |
| SYN-SENT | 客户端 | 客户端已发 SYN,等服务器应答 |
| ESTABLISHED | 双方 | 连接建立成功,正在传数据 |
| FIN-WAIT-1 / FIN-WAIT-2 | 主动关闭方 | 已发 FIN / 已收对方 ACK,等对方 FIN |
| CLOSE-WAIT | 被动关闭方 | 已回 ACK,等自己数据发完再发 FIN |
| TIME-WAIT | 主动关闭方 | 发完最后 ACK,等 2MSL 让旧包消散 |
配合四字口诀理解状态路径:
握手: CLOSED → LISTEN(服务器) / SYN-SENT(客户端) → ESTABLISHED
使用: ESTABLISHED(传数据)
挥手: ESTABLISHED → FIN-WAIT-1 → FIN-WAIT-2 → TIME-WAIT(主动方,等2MSL)
同时被动方:ESTABLISHED → CLOSE-WAIT → LAST-ACK → CLOSED
💡 记忆口诀:"握手进 ESTABLISHED,挥手走 TIME-WAIT;谁先发 FIN 谁负责最后等 2MSL"。
⚠️ 常见错误
- TIME-WAIT 只属于主动关闭方:被动关闭方发完 FIN 收到 ACK 就 CLOSED 了,不用等 2MSL。
- CLOSE-WAIT 是被动关闭方的状态:它代表"我收到你的 FIN 了,但我还在等自己的数据发完"。
- LAST-ACK 不要和 FIN-WAIT 混:FIN-WAIT 是主动方等对方 FIN;LAST-ACK 是被动方发完自己的 FIN 等对方最后确认。
5.10 TCP 与 UDP 总对比 ⭐⭐⭐
两个协议一张表看懂
| 对比维度 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(确认/重传/序号) | 不可靠(尽力而为) |
| 顺序 | 保证按序交付 | 不保证顺序 |
| 传输单位 | 字节流(无边界) | 用户数据报(有边界) |
| 首部开销 | 20 字节 | 8 字节 |
| 流量/拥塞控制 | 有 | 无 |
| 支持广播/组播 | 不支持(点对点) | 支持 |
| 典型应用 | 网页 HTTP、文件 FTP、邮件 SMTP、SSH | 视频直播、语音、DNS、DHCP |
为什么 TCP 是"字节流"而 UDP 是"报文":TCP 把应用层数据看成连续的字节流,按自己的节奏切块打包发送(所以有"序号""重组");UDP 把应用层每次 write 的数据原样作为一个报文发送(有边界,一次发一个)。
怎么选:需要完整、有序、可靠 → TCP(网页、文件、邮件);要快、可容忍少量丢失 → UDP(视频、语音、实时游戏)。
💡 记忆口诀:"TCP 靠谱慢,UDP 快不稳;要完整选 TCP,要实时选 UDP"。
⚠️ 常见错误
- 以为 UDP 不能用于可靠场景:UDP 之上可以自己实现可靠性(如 QUIC 协议在 UDP 上做可靠传输),UDP 只是"不内置"可靠机制。
- 把 DNS 记成 TCP:DNS 查询用 UDP(53 端口),快速一问一答;只有区域传输等少数情况用 TCP。
- TCP 是字节流、UDP 是报文:这一点选择题常考——TCP 无消息边界,UDP 有消息边界。
🧠 记忆口诀
- 传输层两件事:端口找进程(socket=IP+端口),TCP 保可靠。
- TCP 三件套:序号防乱序、确认报进度、超时/重复 ACK 就重传。
- 三次握手:问→应→确认;四次挥手:我关→你确认→你关→我确认。
- SYN 建连、FIN 断开、ACK 确认、RST 重置。
- 流量控制治"接收方装不下"(窗口通告),拥塞控制治"路上堵车"(慢启动/拥塞避免)。
- 慢启动指数探路,拥塞避免线性爬,丢包减半快恢复。
⭐ 考点清单
- 端口号的作用、常见端口(21/22/25/53/80/443)
- UDP 特点:无连接、不可靠、8 字节首部;适合实时场景
- TCP 特点:面向连接、可靠、字节流、20 字节标准首部
- TCP 报文段关键字段:序号、确认号、SYN/ACK/FIN 标志、窗口
- 三次握手的完整流程与各包含义、为什么必须是三次
- 四次挥手流程、为什么是四次、TIME_WAIT 与 2MSL
- 可靠传输:序号重排、累积确认、超时重传、快速重传(3 个重复 ACK)
- 滑动窗口与流量控制:窗口通告、窗口滑动
- 拥塞控制四阶段:慢启动、拥塞避免、快重传、快恢复
- 流量控制(端到端、接收方)与拥塞控制(网络)的区别
- TCP 连接状态:ESTABLISHED、FIN-WAIT、CLOSE-WAIT、TIME-WAIT(2MSL)
- TCP 与 UDP 总对比:字节流 vs 报文、20 vs 8 字节、是否支持广播
📌 中英术语表
| 中文 | English | 说明 |
|---|---|---|
| 传输层 | transport layer | 进程间端到端通信 |
| 端口号 | port number | 标识主机上的具体进程 |
| 套接字 | socket | IP + 端口,标识一个端点 |
| UDP | User Datagram Protocol | 无连接、不可靠、8 字节首部 |
| TCP | Transmission Control Protocol | 面向连接、可靠、字节流 |
| 报文段 | segment | 传输层的数据单元 |
| 序号 | sequence number | 数据首字节的字节号 |
| 确认号 | acknowledgment number | 期望收到的下一字节序号 |
| 标志位 | flag | SYN/ACK/FIN/RST 等 |
| 三次握手 | three-way handshake | 建立连接的三次交互 |
| 四次挥手 | four-way handshake | 释放连接的四次交互 |
| 超时重传 | timeout retransmission | 计时器到点未确认则重发 |
| 快速重传 | fast retransmit | 收到 3 个重复 ACK 立即重发 |
| 累积确认 | cumulative acknowledgment | ack=n 表示 n−1 前都收到 |
| 滑动窗口 | sliding window | 未确认但可发的字节额度 |
| 流量控制 | flow control | 适配接收方能力,靠窗口通告 |
| 拥塞控制 | congestion control | 适配网络状态,避免拥堵 |
| 慢启动 | slow start | 窗口指数增长探路 |
| 拥塞避免 | congestion avoidance | 窗口线性增长 |
| 快恢复 | fast recovery | 丢包后减半窗口恢复 |
| 最大报文段寿命 | MSL | 报文在网络中的最长存活时间 |
| 连接状态 | connection state | LISTEN/ESTABLISHED/FIN-WAIT/TIME-WAIT 等 |
| 字节流 / 报文 | byte stream / datagram | TCP 无边界字节流,UDP 有边界报文 |
| QUIC | QUIC | 基于 UDP 实现可靠传输的新协议 |