中文 English

用了 40 年的 TCP,为什么被 HTTP/3“抛弃”了?

发布时间: 2026-07-18
Network TCP UDP QUIC HTTP3 HTTP2 队头阻塞 计算机网络 科普 TLS 连接迁移

先说结论

先给标题"打假":TCP 并没有被抛弃——文件下载、视频、邮件、SSH,今天依然跑在 TCP 上。但 Web 世界确实换司机了:2022 年 6 月,HTTP/3 成为正式标准(RFC 9114),它不再使用 TCP,而是把网页传输交给了跑在 UDP 上的 QUIC。

TCP 被"换掉"的原因,是三个治不好的"中年病":

  1. 队头阻塞:TCP 是一条必须按顺序交付的字节流,丢一个包裹,后面所有包裹一起罚站;
  2. 握手太贵:传数据之前要先"寒暄" 2-3 个来回(TCP 握手 + TLS 握手),跨洲网络下光打招呼就半秒;
  3. 协议被"焊死":TCP 长在操作系统内核里,中间设备只认"经典款",想改进它比登天难。

QUIC 的药方简单粗暴:把 TCP 的全部智慧,搬到没人管的 UDP 上重做一遍。本文是网络科普三部曲的最后一篇——第一篇讲"网络怎么用",第二篇讲"TCP/IP 为什么这么设计",这一篇讲"连最成功的 TCP,是怎么被自己人换掉的"。所有截图来自真实系统,IP 与主机名已打码。

封面:用了 40 年的 TCP,为什么被 HTTP/3 抛弃了

图 1:Web 换司机了——新司机叫 QUIC,车还是那辆车(UDP 底盘)。


一、Web 换司机的那一天

2022 年 6 月,IETF 发布 RFC 9114,HTTP/3 正式成为标准。这在互联网历史上是个不小的日子:自 1991 年 Web 诞生以来,网页传输第一次不再依赖 TCP。

故事其实更早:2012 年,Google 的工程师们被 TCP 折磨得受不了,干脆在自己家里搞了个实验品叫 gQUIC(Quick UDP Internet Connections),悄悄塞进 Chrome 和自家服务器。跑了近十年、验证了可行性之后,交给 IETF 标准化,就是 2021 年的 QUIC(RFC 9000);而"HTTP 跑在 QUIC 上"这个组合,被命名为 HTTP/3。

这不是纸面标准,是已经上岗的生产系统。下面是我对 Cloudflare 的一次真实 DNS 查询(查的是一种叫 HTTPS 的新型记录,网站用它来"预告"自己会说哪些协议):

真实截图:cloudflare.com 的 HTTPS 类型 DNS 记录

图 2:真实查询结果。alpn="h3,h2" 的意思是:“我会 HTTP/3(h3),也会 HTTP/2(h2),你挑一个”。h3 排在前面——HTTP/3 已经是大厂的首选协议。

那么,把用了 40 多年的 TCP 换掉,图什么?因为 TCP 有三个"中年病",而且一个比一个难治。


二、中年病一:队头阻塞——一个包裹罚站,全队陪着

TCP 的本质是一条有序的字节流。你可以把它想象成高速公路上的一条单车道的收费通道:包裹(数据)必须按编号顺序通过,如果 3 号包裹在路上丢了,那么 4 号、5 号、6 号……哪怕已经全部到达对面,也必须乖乖排队,等 3 号重传到货。这就是"队头阻塞"(Head-of-Line Blocking)。

你可能会说:丢包又不是天天发生。抱歉,丢包就是网络的日常。这是我服务器上真实的 TCP 统计:

真实截图:服务器 TCP 重传统计

图 3:真实 netstat -s 统计。这台机器发出 1665 万个段,重传了 52981 次——每发出 300 多个包裹,就有 1 个要重发。每一次重传,都是一次"全队罚站"。

队头阻塞本来只是"一条连接"的事。但 2015 年的 HTTP/2 做了一件聪明反被聪明误的事:多路复用——浏览器和服务器之间只建一条 TCP 连接,把几十个请求(HTML、CSS、图片、JS)变成几十条"流"(Stream),在同一条连接上交错着跑。

这是我电脑上真实的 HTTP/2 连接日志,注意每条流都有自己的编号:

真实截图:HTTP/2 的流编号

图 4:真实 curl -v 日志。[HTTP/2] [1] OPENED stream——请求被装进编号为 1 的"流"里。HTTP/2 的多路复用确实治好了"应用层"的队头阻塞(请求不用排队了),但底下还是同一条 TCP。

看出问题了吗?HTTP/2 把几十条流绑在了同一条 TCP 单车道上。 以前丢一个包,堵的是一条流;现在丢一个包,几十条流一起罚站——网页上的图片、样式、脚本全卡住。多路复用越成功,队头阻塞越疼。

TCP 队头阻塞 vs QUIC 独立流

图 5:左边(TCP):3 号包裹丢失,所有流一起等它重传;右边(QUIC):每条流独立,只有它自己的那条流需要等。


三、中年病二:握手太贵——还没说正事,先寒暄半秒

TCP 是"打电话",打电话之前要拨号。传任何数据之前,流程是:

  1. TCP 三次握手:1 个来回(RTT)——“喂,听得到吗?"(第一篇讲过);
  2. TLS 加密握手:再 1-2 个来回——“我们对个暗号,接下来的话加密说”。

也就是说,浏览器发出第一个真正的请求之前,至少要空等 2-3 个网络来回。同城网络来回只要几毫秒,无所谓;但跨洲光纤、移动网络,一个来回动辄 100-300 毫秒——光"寒暄"就烧掉半秒钟。

这不是理论,是我在自己电脑上的实测:

真实截图:curl 各阶段耗时,握手花了 573 毫秒

图 6:真实 curl 计时。TCP 接通 279 毫秒(第 1 个来回),TLS 对上暗号 573 毫秒(第 2 个来回)——收到第一个字节之前,0.57 秒全花在打招呼上。

TLS 握手具体要寒暄几句?也是实测:

真实截图:TLS 握手的详细步骤

图 7:真实 curl -v 日志。Client hello → Server hello → Certificate(出示证书)→ Key exchange(交换钥匙)……一长串礼节走完,才能说正事。

其实 TCP 社区早就想治这个病,发明过"TCP Fast Open”(边握手边传数据)。结果呢?几乎没人敢开——因为它要动 TCP 本身,而这就引出了第三个、也是最绝望的病。


四、中年病三:协议被"焊死"——想改 TCP?先给全世界换系统

这是最要命的一病:TCP 已经无法被改进了。

原因有两个:

TCP 被焊死:内核住着 + 中间盒把门

图 8:TCP 的双重困境。左边:想升级它,得给全世界换操作系统;右边:新选项出门就被中间盒拦截。

还记得上一篇说的"我们相信能跑的代码"吗?TCP 如今连"跑新代码"的机会都没有了——它被自己的成功锁死了。

于是 QUIC 的设计者想通了一个看似摆烂、实则精妙的办法:既然 TCP 改不动,那就别改了——把 TCP 的智慧,搬到没人管的 UDP 上重做一遍。

为什么是 UDP?因为中间盒对 UDP 基本"放养"(DNS 等老服务在用,它们不敢乱丢),UDP 成了互联网上最后的自由通道。QUIC 在 UDP 这层"毛坯房"里,自己重新实现了可靠传输、重传、拥塞控制、流量控制——全是 TCP 的看家本领,但现在是"应用自带的代码",想怎么改就怎么改。


五、QUIC 的四张王牌

王牌一:独立流,治队头阻塞。 QUIC 在 UDP 之上原生支持多条独立的流,重传和排序以"流"为单位——3 号包裹丢了,只有它所属的那条流等它,其他流照跑不误(图 5 右半边)。HTTP/2 梦寐以求的多路复用,这才真正兑现。

王牌二:握手内嵌加密,治"太贵"。 QUIC 把 TLS 1.3 直接"焊"进自己的握手:新朋友 1 个来回就能传数据(TCP+TLS 要 2-3 个);访问过的老熟人甚至可以 0-RTT——第一个包裹就直接装着数据出发,连一句寒暄都省了。

握手成本对比:TCP+TLS 要 2-3 个来回,QUIC 只要 1 个甚至 0 个

图 9:左边(TCP):拨号 1 个来回 + 对暗号 1-2 个来回,第 3 个来回才说正事;右边(QUIC):暗号内嵌在拨号里,老熟人开口就谈正事。

王牌三:连接 ID,治"换网断线"。 TCP 靠"双方 IP + 端口"四个值识别一条连接——你从家里走到楼下,WiFi 切成 5G(第一篇讲过这两种网络),IP 一变,所有 TCP 连接全部断开重连。QUIC 不看 IP,它给每条连接发一个"工牌"(Connection ID):网络随便换,只要工牌还在,视频通话、下载都不中断。

连接迁移:WiFi 切 5G,工牌不变,连接不断

图 10:拿着同一张工牌(Connection ID)从 WiFi 走到 5G——对 QUIC 来说,你还是你。

王牌四:用户态 + 全加密,治"焊死"。 QUIC 是跟着 App 走的普通代码(Chrome 升级,QUIC 就升级),不用等操作系统更新;更狠的是,它把包括包头在内的几乎所有内容都加密——中间盒除了"这是一个 UDP 包裹"之外什么也看不见,自然也没法插手干预。你不是爱僵化吗?那我什么都不让你看。

QUIC 用户态 + 全加密 vs TCP 内核态 + 明文头

图 11:左边(TCP):住在内核,升级靠换系统,包头明文,中间盒随便看随便管;右边(QUIC):跟着 App 走,随时升级,全身加密,中间盒只能干瞪眼。


六、TCP 真的被抛弃了吗?

没有,而且差得远。今天的互联网上:

所以准确的说法是:TCP 没有被淘汰,它只是第一次遇到了"能接过接力棒的人”。 在 Web 这条赛道上,更合适的选手上场了;而 TCP 依然是整个互联网的顶梁柱。


七、最有意思的结尾:这不是叛逆,是家风的传承

如果你读过本系列的第二篇(TCP/IP 的设计哲学),会发现 HTTP/3 的故事简直是那 6 条哲学的"期末示范":

TCP 没有输。它只是把"继续演化"的接力棒,交到了 QUIC 手里——而 QUIC 学走路时模仿的每一个动作,都是 TCP 教的。


Q&A

Q1:我的浏览器现在在用 HTTP/3 吗? 很可能在用。Chrome、Edge、Firefox、Safari 都默认支持 HTTP/3,Google、Cloudflare、Meta、B站等早已开启——你可以用图 2 里的方法查常去的网站有没有 alpn="h3"

Q2:为什么不直接发明一个全新的传输协议,非要套在 UDP 上? 因为中间盒会把不认识的协议直接丢弃——当年比 TCP 更先进的 SCTP 就是这么被饿死的。套在 UDP 里是"伪装成普通人",先活下来,再谈理想。

Q3:0-RTT 会不会有安全问题? 会有一种叫"重放攻击"的隐患:坏人可以原样重发你的第一个数据包。所以 0-RTT 只适合查询类(幂等)请求,转账类操作必须等握手完成——QUIC 的设计者把这道门留给了应用自己把守。

Q4:HTTP/3 能让我家网速变快吗? 分场景:网络好、延迟低时,你几乎无感;但在地铁上、电梯里、跨洲访问、信号差的角落(高延迟、爱丢包的地方),提升会非常明显——这正是它被发明出来的原因。

Q5:都 HTTP/3 了,学网络还有必要学 TCP 吗? 更有必要了。QUIC 的每一个特性,都是"TCP 某个问题"的标准答案——不理解 TCP 的队头阻塞、握手成本、内核僵化,就永远看不懂 QUIC 为什么长这样。


从 1974 年的 8 页论文,到 2022 年的 HTTP/3,中间隔了 48 年。TCP 的故事告诉我们:真正伟大的设计,不是永远不会被超越,而是它定义的战场规则,连超越它的人都必须遵守