TCP 与 UDP:从三次握手到拥塞控制
0. 元信息
- 主题路径:
docs/topics/network/subtopics/tcp-and-udp/ - 父主题:
network - 主分类:计算机基础
- 辅助分类:工程技术
- 适合对象:懂 IPv4/IPv6 报文、路由、ICMP,能用
tcpdump抓包的学习者 - 建议周期:4~5 周(每周 6~8 小时,含抓包、命令实验、协议分析)
- 前置知识:
tcp-ip-stack;会ss、ip、ping基本用法 - 最终目标:能读懂 TCP 头字段与三次握手/四次挥手、解释滑动窗口与四种拥塞控制算法、用
ss -tin/iperf3/tcpdump -nn -S排查延迟与吞吐问题、说出 UDP 与 QUIC 的取舍
1. 学习路线
传输层职责与端口
→ UDP 头与无连接语义
→ TCP 头字段
→ 三次握手与四次挥手
→ 状态机与 TIME_WAIT
→ 可靠传输:序列号、ACK、重传
→ 流量控制:滑动窗口与 rwnd
→ 拥塞控制:cwnd、慢启动、拥塞避免
→ 经典算法:Reno / Cubic / BBR
→ UDP 适用场景:DNS / VoIP / 实时游戏
→ QUIC 演进:解决队头阻塞、握手合并
→ Linux 调参与抓包综合排障
每一步都要抓一次包。TCP 字段多、背不下来,靠抓包对照才记得住。
2. 阶段周数分配
| 阶段 | 4 周方案 | 5 周方案 | 备注 |
|---|---|---|---|
| 1. 传输层与 UDP | 0.5 周 | 0.5 周 | UDP 头 + DNS 抓包 |
| 2. TCP 头与三次握手 | 0.5 周 | 0.75 周 | tcpdump -S -nn 抓 SYN/SYN-ACK/ACK |
| 3. 状态机与挥手 | 0.5 周 | 0.75 周 | 11 个状态 + TIME_WAIT 之谜 |
| 4. 滑动窗口与重传 | 0.5 周 | 0.75 周 | rwnd、累积 ACK、选择性重传 |
| 5. 拥塞控制 | 1 周 | 1.25 周 | 慢启动、cwnd、四大算法 |
| 6. UDP 实战与 QUIC | 0.5 周 | 0.5 周 | DNS、NTP、QUIC 抓包 |
| 7. 综合排障 | 0.5 周 | 0.5 周 | ss -tin + iperf3 + tcpdump 联用 |
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 可观察学会标准 |
|---|---|---|---|
| 1. 传输层定位 | 端口、socket、多路复用、TCP vs UDP 语义 | 一张 5 元组变化图 | 能解释 TCP 与 UDP 各自解决的什么问题 |
| 2. UDP | 头(length + checksum)、无连接、尽最大努力 | 抓一次 DNS 53/UDP 交互 | 能从抓包看出发送/响应端口和长度 |
| 3. TCP 头 | 16 位源/目的端口、32 位序列号、32 位 ACK、头长、flags、window、checksum、urgent | 抓一次 HTTP 80 连接的三次握手 | 能从 hex 找出 SYN、ACK、seq、ack_seq |
| 4. 三次握手 | SYN、SYN-ACK、ACK、ISN 随机化、半打开防御 | 抓包 + 解释每一步 | 能解释为什么三次而不是两次 |
| 5. 四次挥手 | FIN、ACK、CLOSE_WAIT、TIME_WAIT、2MSL | 抓 HTTP 关闭的 FIN 包 | 能解释 TIME_WAIT 多的原因与 SO_REUSEADDR |
| 6. 滑动窗口 | rwnd、累积 ACK、零窗口、糊涂窗口综合征 | ss -tin 看窗口大小 | 能解释为什么需要滑动窗口 |
| 7. 拥塞控制 | cwnd、慢启动、拥塞避免、ssthresh | ss -tin 看 cwnd init | 能区分 rwnd 与 cwnd |
| 8. 经典算法 | Tahoe、Reno、Cubic(默认)、BBR | 同一链路换算法测吞吐 | 能解释 BBR 为什么在丢包网络更优 |
| 9. UDP + QUIC | DNS、QUIC 头、连接迁移、0-RTT、队头阻塞 | 抓一次 HTTP/3 443/UDP | 能说出 QUIC 相对 TCP+TLS 的核心改进 |
阶段 9 真实场景:HTTP/3 在公网移动场景下比 HTTP/1.1 + TLS 1.3 over TCP 抗丢包能力强,能从 QUIC 抓包看 connection_id 验证连接迁移。
4. 第一周任务
| 日 | 任务 | 当天交付 |
|---|---|---|
| Day 1 | ss -tunlp 看本机监听 socket;netstat -s 看 TCP 重传统计 | 一份监听清单 + TCP 统计 |
| Day 2 | tcpdump -ni any -nn -S udp port 53 抓一次 dig 请求;看 UDP 头字段 | DNS 抓包 + 字段标注 |
| Day 3 | curl http://example.com 同时 tcpdump -ni any -nn -S 'tcp port 80' 抓三次握手 | 三次握手 pcap + seq/ack 标注 |
| Day 4 | 故意 tc qdisc add dev lo root netem loss 30% 制造丢包;tcpdump 看 TCP 重传 | 丢包 + 重传对照记录 |
| Day 5 | ss -tin 看活跃连接的 cwnd、rwnd、rtt、retrans;阅读 man 7 tcp | 一份连接参数清单 |
| Day 6 | iperf3 -s 在两台机器间跑 TCP/UDP 打流;tcpdump -nn -S 同时抓 | iperf3 报告 + 抓包 |
| Day 7 | 项目:抓一次完整 TCP 生命周期:连接建立 → 传输数据 → 关闭,包含三次握手、数据 ACK、四次挥手 | 完整 pcap + 字段标注 + 复盘 |
Day 7 拆解
步骤 A —— 最小可用(60 分钟)
tcpdump -ni any -w /tmp/tcp.pcap -nn -S 'tcp and host <target>'抓 60 秒;curl http://<target>/触发完整连接;- 用
tcpdump -r /tmp/tcp.pcap -nn -S列出所有包; - 把三次握手和四次挥手的 seq/ack/flags 标到 16 进制输出上。
步骤 B —— 补齐边界(30 分钟)
- 在抓包中找一段数据传输,对比每包的 seq 增量与 ACK 号;
- 故意
tc qdisc add加 10% 丢包,看重传包([TCP Retransmission]或 fast retransmit); - 抓
ss -tin输出与 pcap 对照,写到notes/week1-day7.md。
进阶:稳定通过后,再叠加
tcpdump -nn -S 'tcp[tcpflags] & tcp-syn != 0'单独看 SYN 包。
5. 阶段通用验收
- 不看 RFC 也能画出 TCP 头 20 字节的字段分布;
- 用自己的话解释「为什么三次握手」「为什么 TIME_WAIT 等 2MSL」;
- 画一张图:建立连接 → 传输数据 → 关闭过程中 seq/ack/window 变化;
- 测试异常:SYN 攻击、半打开、RST 强制关闭、零窗口、丢包触发重传;
- 准备 3 组自定义数据并贴实际抓包(不同 RTT、不同丢包率、不同 cwnd 算法);
- 记录每次抓包的 BPF 过滤器和命令;
- 能修改
sysctl拥塞控制算法并验证切换。
6. 最终验收
- 独立完成:画 TCP 头、解释三次握手、识别 4 种拥塞控制算法、抓一次完整 TCP 生命周期;
- 至少完成 6 个实验(三次握手、四次挥手、滑动窗口、拥塞控制、UDP 抓包、QUIC 抓包);
- 完成 1 个综合排障项目:模拟一条 RTT 升高 / 丢包率升高 / cwnd 卡住的链路,定位根因;
- 能用 15 分钟讲清楚 TCP 是怎么从「无连接不可靠的 IP」上做到「可靠字节流」的。
7. 综合项目
首选:TCP 链路质量诊断(必做:在两台 Linux 上用 tc netem 注入延迟 / 丢包 / 抖动,用 ss -tin / iperf3 / tcpdump 三件套定位)。
备选:
- 抓包分析 100 条 UDP/TCP 报文并分类;
- 用
iptables模拟端口重置并验证 RST 行为; - HTTP/3 over QUIC 抓包对比 HTTP/1.1 over TCP。
综合项目必做要求:
- 场景描述:网络拓扑、预期行为、实际行为;
- 工具选择理由:为什么用
ss -tin而不是netstat?为什么用iperf3而不是curl? - 核心分析:每一次现象的判断依据与根因定位;
- 复现脚本:可重复运行的
tc qdisc add/iperf3/tcpdump命令; - 边界测试:换丢包率、换 RTT、换 cwnd 算法都验证过;
- 运行说明:环境依赖(
iproute2、tcpdump、iperf3)、复现步骤; - README:项目介绍、目录结构、复盘;
- 复盘记录:用时、难点、收获、下一步。
复盘项目交付物统一存到 notes/:
notes/design.md:拓扑、命令、定位逻辑;notes/test.md:每组数据输入、期望、实际;notes/retrospective.md:踩过的坑与改进点。
本主题贡献
本主题沉淀 TCP 三次握手/四次挥手、滑动窗口与四大拥塞控制算法(Reno/Cubic/BBR),以及 QUIC over UDP 多路复用的工程化观测,所有结论以 tcpdump -nn -S + ss -tin + iperf3 为证据。
职责(3 项)
- 抓 TCP 三次握手 SYN/SYN-ACK/ACK 序列、四次挥手 FIN/ACK、ISN 随机化与 TIME_WAIT 行为,能解释为什么 TIME_WAIT 等 2MSL 与 SO_REUSEADDR 的边界,以及 SYN flood 下
tcp_max_syn_backlog+ syncookies 的边界; - 区分 rwnd(防接收方被淹)与 cwnd(防网络被淹),用
tc qdisc add注入丢包验证 Reno/Cubic/BBR 在跨运营商链路的吞吐差异,能解释 BBR 基于带宽×RTT 模型而非丢包事件的抗丢包原理; - 抓 HTTP/3 over QUIC 的 Initial/Handshake 包、CRYPTO 帧与 connection_id,验证连接迁移(换 IP 不重连)与 0-RTT 重放风险,能区分 QUIC stream 隔离与 HTTP/2 单连接多 stream 在队头阻塞上的差异。
交付物(4 项)
- 完整 TCP 生命周期 pcap(建立 → 数据 → 关闭),含 SYN、SYN-ACK、ACK、FIN 序列号与 flags 标注(
-S不加会看到相对值 0/1/2); ss -tin输出(cwnd/rwnd/rtt/retrans/ssthresh)与sysctl net.ipv4.tcp_congestion_control切换记录(cubic ↔ bbr);iperf3 -P 4 -w 1M同链路 Cubic vs BBR 30 秒吞吐对比报告,附 RTT/丢包率变量;- HTTP/3 over QUIC 抓包(
curl --http3-only -v+SSLKEYLOGFILE喂 Wireshark),含 connection_id 与 0-RTT Early Data 证据。
指标(3 项)
- TIME_WAIT 比例 ≤ 30%(短连接服务开启
net.ipv4.tcp_tw_reuse后); - TCP 重传率 ≤ 0.5%(
netstat -s/ss -tin retrans采样); - 拥塞控制切换后吞吐提升 ≥ 20%(BBR 相对 Cubic,跨运营商 1% 丢包链路)。
8. 推荐开源资料(按角色分工)
| 角色 | 资料 | 链接 | 用法 |
|---|---|---|---|
| RFC 原文 | RFC 9293 (TCP) | https://www.rfc-editor.org/rfc/rfc9293 | TCP 现状规范(替代 RFC 793) |
| RFC 原文 | RFC 768 (UDP) | https://www.rfc-editor.org/rfc/rfc768 | UDP 全文短,一遍读完 |
| RFC 原文 | RFC 9000 (QUIC) | https://www.rfc-editor.org/rfc/rfc9000 | QUIC 传输 |
| RFC 原文 | RFC 5681 (TCP Congestion Control) | https://www.rfc-editor.org/rfc/rfc5681 | 拥塞控制经典 |
| RFC 原文 | RFC 9438 (TCP CUBIC) | https://www.rfc-editor.org/rfc/rfc9438 | 当前 Linux 默认算法 |
| 论文 | Jacobson 1988 (Congestion Avoidance) | https://ee.lbl.gov/papers/congavoid.pdf | 慢启动与拥塞避免起源 |
| 论文 | BBR: Congestion-Based Congestion Control | https://queue.acm.org/detail.cfm?id=3022184 | BBR 原理 |
| 工具手册 | iperf3 主页 | https://iperf.fr/ | 打流与吞吐测量 |
| 工具手册 | man 7 tcp | man 7 tcp | Linux TCP 实现细节 |
| 工具手册 | ss 命令手册 | https://man7.org/linux/man-pages/man8/ss.8.html | -tin 等参数 |
| 中文讲解 | 美团技术团队「TCP 那些事儿」 | https://tech.meituan.com/ | 国内高质量 TCP 分析 |
| 抓包练习 | Wireshark 官方样例 pcap | https://wiki.wireshark.org/SampleCaptures | TCP/UDP 真实报文 |
许可证提示:Wireshark 样例 pcap 是公开教学资源;iproute2 是 GPL-2.0。复制或参考命令前先确认许可证。
源码阅读时机:Linux TCP 实现源码(
net/ipv4/tcp.c/tcp_input.c/tcp_output.c)放到「阶段 5(拥塞控制)」之后再读;RFC 原文从 Day 1 就开始对照,但不要试图一次通读——按当前阶段挑相关章节。
9. 学习资料汇聚(v0.3 自包含)
本节内容基于公开 RFC、Linux 手册与个人整理,标注「由本计划生成」处为计划自写。本节是子主题自包含的最后一节,不再依赖
notes/子目录。
9.1 背景与动机
- 1974 年 Vint Cerf 与 Bob Kahn 发表《A Protocol for Packet Network Intercommunication》,TCP 雏形。
- 1981 年 RFC 793 标准化 TCP,1983 年随 ARPANET 切换 TCP/IP 协议栈,全球互联网核心协议。
- 1988 年 Van Jacobson 发表拥塞避免论文,解决「TCP 雪崩致死」问题,奠定慢启动与拥塞避免算法。
- 1990 年代 UDP 被广泛用于 DNS(53/UDP)、NTP(123/UDP)、实时音视频等场景——这些场景要么短报文、要麼容忍丢包,对 TCP 的握手和重传太重。
- 2016 年后 Google 推出 QUIC(RFC 9000),在 UDP 之上重做可靠传输,解决 TCP+TLS 握手延迟与队头阻塞。
- 一句话总结:TCP 是「可靠的字节流」,UDP 是「不可靠的数据报」;QUIC 是在 UDP 上重做的「现代版 TCP」。选错协议 = 性能砍半,选对 = 免费拿到 10 倍吞吐。
9.2 概念地图
flowchart LR
App[应用层] --> Socket
Socket --> TCP[TCP]
Socket --> UDP[UDP]
Socket --> QUIC[QUIC / HTTP/3]
TCP --> State[状态机]
TCP --> Flow[流量控制 rwnd]
TCP --> Cong[拥塞控制 cwnd]
TCP --> Retrans[重传]
Cong --> Reno[Reno]
Cong --> Cubic[Cubic]
Cong --> BBR[BBR]
UDP --> DNS
UDP --> RTP[实时音视频]
QUIC --> Stream[多路复用流]
QUIC --> 0RTT[0-RTT]
QUIC --> Migration[连接迁移]
TCP --> IP
UDP --> IP
QUIC --> IP
关系说明:
TCP是核心,向上接 Socket,向下交 IP;TCP内部三件套:状态机、流量控制(rwnd)、拥塞控制(cwnd),重传受两者共同驱动;Reno是经典教科书算法,Cubic是 Linux 默认,BBR是 Google 提出的基于模型的新一代;UDP是「裸」的传输层,几乎不加东西;QUIC建在 UDP 之上,引入多路复用流与 0-RTT 握手,解决 TCP+TLS 的队头阻塞与延迟。
9.3 基础知识讲解
经典论文 / 经典书籍 / 优秀博客 / 核心人物 / 开发方法 五大类,每类 ≥3 条。
经典论文 / RFC(必读)
| 资料 | 角色 | 评分 | 链接 |
|---|---|---|---|
| RFC 9293 — Transmission Control Protocol | TCP 现状规范 | 5 | https://www.rfc-editor.org/rfc/rfc9293 |
| RFC 768 — User Datagram Protocol | UDP 全文 | 5 | https://www.rfc-editor.org/rfc/rfc768 |
| RFC 9000 — QUIC | QUIC 传输 | 5 | https://www.rfc-editor.org/rfc/rfc9000 |
| RFC 5681 — TCP Congestion Control | 拥塞控制经典 | 5 | https://www.rfc-editor.org/rfc/rfc5681 |
| RFC 9438 — CUBIC | 当前 Linux 默认算法 | 4 | https://www.rfc-editor.org/rfc/rfc9438 |
| RFC 6298 — TCP RTO 计算 | RTO 重传策略 | 4 | https://www.rfc-editor.org/rfc/rfc6298 |
| Jacobson 1988 Congestion Avoidance | 慢启动起源 | 5 | https://ee.lbl.gov/papers/congavoid.pdf |
| BBR: Congestion-Based Congestion Control | BBR 原理 | 5 | https://queue.acm.org/detail.cfm?id=3022184 |
经典书籍(系统化)
| 资料 | 角色 | 评分 | 链接 |
|---|---|---|---|
| 《TCP/IP 详解 卷 1:协议》(Richard Stevens) | 协议层最经典 | 5 | https://www.amazon.com/TCP-Illustrated-Volume-Protocols/dp/0321336313 |
| 《UNIX 网络编程 卷 1》(Stevens) | Socket 与协议实现 | 5 | https://www.unixnetworkprogramming.com/ |
| 《计算机网络:自顶向下方法》(Kurose & Ross) | 教学级系统讲解 | 4 | https://gaia.cs.umass.edu/kurose_ross/ |
| 《Linux 高性能服务器编程》(游双) | Linux 网络栈工程 | 4 | https://book.douban.com/subject/24722642/ |
| 《TCP/IP 架构、设计与应用》(Feit) | 协议族现代视角 | 4 | https://www.amazon.com/TCP-Architecture-Protocols-Implementation/dp/0070607314 |
优秀博客(按问题查)
| 资料 | 角色 | 评分 | 链接 |
|---|---|---|---|
| Julia Evans「Networking!」(zines) | 抓包与命令可视化 | 5 | https://jvns.ca/networking-zine.pdf |
| Cloudflare Blog(TCP/QUIC 系列) | TCP/QUIC 深入 | 4 | https://blog.cloudflare.com/tag/tcp/ |
| Marek Majkowski(Cloudflare) | Linux 调参与排障 | 4 | https://blog.cloudflare.com/tag/tcp/ |
| 美团技术团队「TCP 那些事儿」 | 中文长文深度解析 | 5 | https://tech.meituan.com/ |
| APNIC Blog | 运营商视角 + 排障 | 4 | https://blog.apnic.net/ |
| 张彦飞「TCP 三次握手与四次挥手」 | 中文原理图解 | 3 | https://yuanfux.github.io/ |
核心人物(知道谁定的规范)
| 人物 | 贡献 | 关键出处 |
|---|---|---|
| Vint Cerf | TCP/IP 共同设计者 | 1974 论文 |
| Bob Kahn | TCP/IP 共同设计者 | 1974 论文 |
| Jon Postel | RFC 编辑、TCP/UDP 标准化 | RFC 793/768 |
| Van Jacobson | 慢启动、拥塞避免、TCP 头压缩 | 1988 论文 |
| Jim Gettys | BBR 共同提出者 | 1990s HTTP/1.1 设计 |
| Neal Cardwell | BBR、Linux TCP 调参 | Linux Kernel 维护者 |
| Yuchung Cheng | Linux TCP 团队 | CUBIC 改进 |
| Jana Iyengar | QUIC 设计 | IETF QUIC WG 主席 |
开发方法(动手习惯)
| 方法 | 适用 | 关键点 |
|---|---|---|
| 抓包驱动学习 | TCP 任何机制 | 看到 seq/ack/flags 变化比看图快 10 倍 |
ss -tin 必看 | 实时连接调参 | 抓现场连接的真实 cwnd、rwnd、rtt |
tcpdump -nn -S | 数字不解析 | 不加 -S seq 是相对值,看不出绝对增长 |
iperf3 打流 | 复现吞吐与延迟 | 客户端/服务端分开跑,记录并发流数 |
tc netem 注入 | 模拟丢包/延迟 | 永远先在测试环境复现,再回生产 |
| BPF 过滤 | 抓包 | tcp[tcpflags] & tcp-syn != 0 单看 SYN |
man 7 tcp / man 7 ip | Linux 实现细节 | 看到 tcp_no_metrics_save 等默认值 |
缺失部分:
tcpdump的-dd输出语法、BPF 字面量在不同 libpcap 版本的差异。本计划不重写工具手册;查man pcap-filter即可。
9.4 经典问题与经典案例
| # | 问题 | 为什么会重要 | 最简答案 |
|---|---|---|---|
| 1 | TIME_WAIT 太多 | 短连接服务 TIME_WAIT 一旦上万,端口耗尽 | 开启 SO_REUSEADDR、调整 net.ipv4.ip_local_port_range |
| 2 | SYN flood | 攻击者只发 SYN 不回 ACK | 启用 syncookies、合理调 tcp_max_syn_backlog |
| 3 | 队头阻塞(HoL) | TCP 丢一包阻塞整条流 | HTTP/2 多路复用缓解但未根除;QUIC 真正解决 |
| 4 | Nagle 与延迟应答 | 小包合并导致延迟升高 | 关闭 TCP_NODELAY、关闭 TCP_QUICKACK |
| 5 | 零窗口死锁 | 接收方 rwnd=0 后丢了窗口更新 | 持久化零窗口探测 + 可调整 tcp_zero_window_drop |
| 6 | 滑动窗口不前进 | 接收方应用层读慢 | 调大 net.ipv4.tcp_rmem、应用层读优化 |
| 7 | 拥塞控制算法选错 | 跨运营商丢包多,Cubic 吞吐崩 | 切 BBR:sysctl net.ipv4.tcp_congestion_control=bbr |
| 8 | 重传风暴 | 一次丢包触发多次重传 | 看 RTO 与 dup ACK;Karn 算法不重传 RTT 测量包 |
| 9 | 连接迁移失败 | TCP 靠 4 元组,移动换 IP 就断 | 用 QUIC,看 connection_id 不变继续 |
| 10 | UDP 巨型包被截 | 应用发 64KB,IPv4 链路只让 1500B | 分片;建议 MTU 不超 1200B,避免 IPv4/IPv6 路径分片 |
| 11 | DNS 抓包看不到响应 | TCP 53 替代 UDP 53,怀疑劫持 | 抓 TCP;DNS 53 早就支持 TCP |
| 12 | QUIC 抓包是乱码 | 几乎全部加密 | 看 Initial 包 + CRYPTO 帧;用 Wireshark QUIC 解密密钥 |
9.5 学习难点
概念难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 序号 vs 确认号 | seq 是数据首字节,ack 是期望下一字节 | 抓一个包画箭头:SYN seq=x, ack=0 |
| flags 位多 | 6 位 TCP flags 难记 | 按位算:SYN=0x02, ACK=0x10, FIN=0x01 |
| rwnd vs cwnd | 两个窗口都管速率,作用不同 | rwnd 防接收方被淹,cwnd 防网络被淹 |
| TIME_WAIT 2MSL | 主动关闭方要等 2 个 MSL | 目的是让对端能收到最后的 ACK |
| 慢启动阈值 | ssthresh 从哪来 | 第一次丢包时把 cwnd/2 作为 ssthresh |
| BBR 模型 | 不靠丢包,靠带宽×RTT 估计 | 读 BBR 论文的 BtlBw 与 RTprop 估计 |
思维难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 状态机 11 个状态 | 记不住 | LISTEN → SYN_SENT → SYN_RCVD → ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → CLOSE_WAIT → LAST_ACK → TIME_WAIT → CLOSED |
| 重传与快速重传 | 触发条件不同 | 超时重传:RTO 到;快速重传:3 个 dup ACK |
| 拥塞控制的「避免」 | 拥塞避免 ≠ 流量整形 | 拥塞避免是「接近极限时收敛」,不是「停下来」 |
| 队头阻塞 | TCP 与 HTTP/2 都有 | TCP 字节流级;HTTP/2 单连接级;QUIC 流级 |
| 0-RTT 风险 | 重放攻击 | 0-RTT 只能用于幂等请求 |
工程难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
ss -tin 字段多 | 不知道哪个是关键 | 记住 cwnd、rwnd、rtt、retrans 四个 |
| 抓包 seq 不变 | 没加 -S 看到的是相对值 | 必加 -S;否则永远是 0/1/2 |
| 多网卡混淆 | -i any 时间戳乱 | 改用具体接口 -i eth0 |
| iperf3 打流慢 | 默认单流,挤不动 BDP | 增加 -P 4 并发,或加 -w 1M 窗口 |
| 算法切换不生效 | sysctl 改了但内核没加载 | `lsmod |
| QUIC 抓包解密 | TLS 1.3 加密 | 用 SSLKEYLOGFILE 喂 Wireshark |
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 版本 | 发布组织 | 状态 | 许可证 / 可访问性 |
|---|---|---|---|---|
| TCP (RFC 9293) | 2022 | IETF / TSVWG | 现行标准 | 免费公开 |
| UDP (RFC 768) | 1980 | IETF / TSVWG | 现行标准 | 免费公开 |
| TCP Congestion Control (RFC 5681) | 2009 | IETF / TSVWG | 现行标准 | 免费公开 |
| CUBIC (RFC 9438) | 2023 | IETF / TSVWG | 现行标准 | 免费公开 |
| QUIC (RFC 9000) | 2021 | IETF / QUIC WG | 现行标准 | 免费公开 |
| iperf3 | 持续更新 | iperf3 项目 | 工具 | BSD-3-Clause |
| Linux kernel net stack | 持续更新 | Linux Foundation | 事实标准 | GPL-2.0 |
9.6.2 Scope
- TCP:提供面向连接的可靠字节流;含流量控制、拥塞控制、错误检测与重传;
- UDP:提供无连接尽最大努力交付的数据报;不重传、不拥塞控制、不保证顺序;
- QUIC:在 UDP 之上重做 TCP+TLS 的能力,包含多路复用、0-RTT、连接迁移;
- iproute2 / iperf3:工具层,提供观测与测量;
- Linux kernel net stack:上述协议的具体实现。
不适用:实时流媒体裸协议(用 RTP/SRTP)、可靠消息队列(用 QUIC/AMQP)、应用层多路复用(用 HTTP/2、HTTP/3)。
9.6.3 Structure
TCP 头(20 字节,无选项):
| 偏移 | 字段 | 长度 | 说明 |
|---|---|---|---|
| 0-1 | Source Port | 2 字节 | |
| 2-3 | Destination Port | 2 字节 | |
| 4-7 | Sequence Number | 4 字节 | 当前段首字节 |
| 8-11 | Acknowledgment Number | 4 字节 | 期望下一字节 |
| 12 | Data Offset + Reserved | 1 字节 | 头长(4 位) |
| 13 | Flags | 1 字节 | CWR/ECE/URG/ACK/PSH/RST/SYN/FIN |
| 14-15 | Window Size | 2 字节 | rwnd |
| 16-17 | Checksum | 2 字节 | 必选 |
| 18-19 | Urgent Pointer | 2 字节 |
UDP 头(8 字节):
| 偏移 | 字段 | 长度 |
|---|---|---|
| 0-1 | Source Port | 2 字节 |
| 2-3 | Destination Port | 2 字节 |
| 4-5 | Length | 2 字节 |
| 6-7 | Checksum | 2 字节(IPv4 可选,IPv6 必选) |
TCP flags 关键字:
| Flag | 名称 | 用途 |
|---|---|---|
| SYN | 同步 | 建立连接 |
| ACK | 确认 | 确认数据 |
| FIN | 结束 | 关闭连接 |
| RST | 复位 | 强制关闭 |
| PSH | 推送 | 立即交付应用 |
| URG | 紧急 | 紧急指针有效 |
| CWR/ECE | 拥塞 | ECN 反馈 |
9.6.4 Ecosystem
- 内核实现:Linux kernel 的
net/ipv4/tcp.c/net/ipv4/tcp_input.c/net/ipv4/tcp_output.c/net/ipv4/udp.c;BBR 在net/ipv4/tcp_bbr.c;Cubic 在net/ipv4/tcp_cubic.c; - 用户态工具:
iproute2(ss、ip)、iperf3(打流)、tcpdump/wireshark(抓包)、tc(netem注入)、nftables(防火墙); - QUIC 实现:Chromium’s
net/quic、Cloudflarequiche、Microsoftmsquic、Facebookmvfst、Nginx/OpenResty(HTTP/3); - 事实标准 vs 标准本身:
- Linux 默认拥塞控制是 Cubic(
net.ipv4.tcp_congestion_control可改); tcpdump默认不解密 QUIC,需要 Wireshark 配合SSLKEYLOGFILE;- 大多数 Linux 发行版默认
tcp_fastopen关闭,需要手动sysctl开启。
- Linux 默认拥塞控制是 Cubic(
9.6.5 Depth Tiers
| 层级 | 名称 | 必须看到什么 |
|---|---|---|
| L0 | 知道存在 | 知道 TCP 是面向连接可靠字节流;UDP 是无连接;QUIC 是 UDP 上的现代传输 |
| L1 | 看得懂示例 | 看到 ss -tn 的状态列能猜出是连接还是监听 |
| L2 | 能正确调用 | 能用 tcpdump 抓 TCP 三次握手,用 iperf3 打流 |
| L3 | 能解释与排错 | 能解释为啥 TIME_WAIT 多、为啥换 BBR 吞吐涨、为啥 QUIC 抗丢包 |
| L4 | 能设计与扩展 | 能调 sysctl 优化大 RTT 高丢包链路,能看懂 tcp_input.c 与 Linux 算法切换 |
本计划目标:阶段 9 综合排障时达到 L3。
9.6.6 Source
- RFC Editor:所有 TCP/UDP/QUIC 原文(
https://www.rfc-editor.org/); - IANA Protocol Numbers:协议号与端口号权威分配(
https://www.iana.org/assignments/protocol-numbers/); - iperf3 官方主页(
https://iperf.fr/); - Linux
man 7 tcp/man 7 udp/man 8 ss/man 8 tcpdump; - 引用版本快照日期:2026-07-30。
10. 常见误区
- 把 TCP 当成「保证 100% 到达」:TCP 不保证,分组重传仍可能因超时放弃;
- 抓包不指定接口:用
-i any在多网卡主机上时间戳会乱; tcpdump不加-S:看到 seq=0/1/2 以为是串号;- 以为
ss -t就是 TCP 全信息:ss -tin才有 cwnd/rtt/retrans; - 改
sysctl不sysctl -p:编辑完没生效; - 关闭 Nagle
TCP_NODELAY当成万能:会让小包增多,反而增加头部开销; - 把 QUIC 当成「QUIC = HTTP/3」:QUIC 是传输协议,HTTP/3 是其上跑的 HTTP;
- 切换 BBR 不装模块:
modprobe tcp_bbr漏了会报No such file or directory; - BENCHMARK 噪声:单次
iperf3跑 5 秒拿不到稳定值,要跑 30 秒以上; - 用
time curl测延迟:TCP 握手就 1 个 RTT,测延迟应用curl -w '%{time_connect}'; - 把 UDP 当成「更快的 TCP」:UDP 不可靠,需要应用层补足;
- 抓包只看 SYN 包就下结论:完整生命周期才能解释为什么 RST / FIN 出现。
11. 所有知识点分类(统一规则)
按本仓库统一分类规则(与父主题一致):
- 编程语言
- 数据结构与算法
- 计算机基础:网络协议、操作系统、组成原理
- 工程技术
- Web 与后端
- 前端与客户端
- 数据与人工智能
- 项目与职业能力
本计划归属:计算机基础 主 + 工程技术 辅。