HTTP 各版本演进与 HTTPS 原理详解

一、先搞清楚 HTTP 是什么

HTTP(HyperText Transfer Protocol)就是浏览器和服务器之间"对话"的规则。你在浏览器输入一个网址,浏览器按照 HTTP 规则发一个请求,服务器按照 HTTP 规则回一个响应。

vbscript 复制代码
浏览器:「我要 /index.html」          →  请求(Request)
服务器:「给你,200 OK,内容如下...」   ←  响应(Response)

HTTP 从 1991 年诞生到现在,经历了 5 个大版本。每个版本都是为了解决上一个版本的痛点。


二、HTTP/0.9(1991)------ 最原始的版本

特点

  • 只支持 GET 方法
  • 没有请求头、没有响应头
  • 只能传 HTML 文本
  • 响应完就断开连接

一次对话长这样

bash 复制代码
请求:GET /hello.html
响应:<html>Hello World</html>
(连接断开)

就这么简单粗暴。没有状态码,没有 Content-Type,啥都没有。

存在的问题

  • 只能传 HTML,不能传图片、CSS、JS
  • 没有任何元数据(不知道内容多大、什么类型、什么编码)
  • 每次请求都要新建连接

三、HTTP/1.0(1996)------ 有模有样了

解决了什么

新增能力 说明
请求头 & 响应头 可以携带元数据了(Content-Type、Content-Length 等)
多种方法 GET、POST、HEAD
状态码 200、404、500 等,知道请求成功还是失败了
Content-Type 可以传图片、音频、视频,不再局限于 HTML
版本号 请求行里带上 HTTP/1.0

一次对话长这样

yaml 复制代码
请求:
GET /logo.png HTTP/1.0
Host: www.example.com
Accept: image/png

响应:
HTTP/1.0 200 OK
Content-Type: image/png
Content-Length: 4096

(图片二进制数据)
(连接断开)

存在的问题

最大的问题:短连接。 每个请求都要经历 TCP 三次握手 → 传数据 → 四次挥手。

一个网页有 1 个 HTML + 10 个图片 + 3 个 CSS + 5 个 JS = 19 个请求,就要建立 19 次 TCP 连接。

css 复制代码
连接1:[三次握手] → GET /index.html → [响应] → [四次挥手]
连接2:[三次握手] → GET /style.css  → [响应] → [四次挥手]
连接3:[三次握手] → GET /logo.png   → [响应] → [四次挥手]
...重复 19 次

每次握手和挥手都要消耗时间和系统资源,极其浪费

虽然有些实现支持非标准的 Connection: keep-alive,但这不是规范的一部分,行为不统一。


四、HTTP/1.1(1997)------ 用了二十多年的主力

解决了什么

1. 持久连接(Keep-Alive)------ 最重要的改进

默认开启 TCP 连接复用。一个连接可以发多个请求,不用每次都握手挥手。

复制代码
HTTP/1.0:
  连接1 → 请求1 → 响应1 → 断开
  连接2 → 请求2 → 响应2 → 断开
  连接3 → 请求3 → 响应3 → 断开

HTTP/1.1:
  连接1 → 请求1 → 响应1 → 请求2 → 响应2 → 请求3 → 响应3 → 断开

2. 管线化(Pipelining)

理论上可以不等响应就发下一个请求:

markdown 复制代码
客户端:请求1 → 请求2 → 请求3 →
                                  等待...
服务端:                    ← 响应1 ← 响应2 ← 响应3

但实际几乎没人用(原因见下面的问题)。

3. 分块传输(Chunked Transfer)

不需要预先知道内容的总大小,边生成边发送:

makefile 复制代码
HTTP/1.1 200 OK
Transfer-Encoding: chunked

5\r\n
Hello\r\n
6\r\n
 World\r\n
0\r\n
\r\n

适用场景:服务端流式输出(比如 ChatGPT 的逐字输出)。

4. 其他新增

能力 说明
Host 头必选 一个 IP 可以托管多个域名(虚拟主机)
Cache-Control 更精细的缓存控制(替代 Expires)
Range 请求 支持断点续传(下载了一半断了,可以接着下)
100 Continue 先问服务器"我要发一个大文件,你准备好了吗?"
PUT / DELETE / OPTIONS / PATCH 更多的方法,RESTful API 的基础

存在的问题

问题一:队头阻塞(Head-of-Line Blocking)

这是 HTTP/1.1 最致命的问题。

虽然支持管线化,但响应必须按请求的顺序返回。如果第一个请求处理很慢,后面的请求即使已经处理完了,也必须排队等着。

复制代码
请求顺序:请求1(慢查询)→ 请求2(静态图片)→ 请求3(CSS)

实际情况:
  请求1 ████████████████████░░░░░(处理中...3秒)
  请求2 ░░░░░░░░░░░░░░░░░░░████░  (早就好了,但必须等请求1)
  请求3 ░░░░░░░░░░░░░░░░░░░░░░██  (也在排队等)

就像高速公路只有一条车道,前面的大卡车开得慢,后面的跑车再快也超不过去。

问题二:并发限制的妥协

为了绕开队头阻塞,浏览器的做法是 对同一个域名开 6 个并行 TCP 连接

但这导致了新的问题:

  • 每个连接都要三次握手 + TLS 握手,开销不小
  • 服务器要维护大量连接
  • 催生了"域名分片"等 hack 手段(把资源分散到 cdn1.xxx.comcdn2.xxx.com 来突破 6 个限制)

问题三:头部冗余

每个请求都要带上完整的头部(Cookie、User-Agent、Accept 等),这些头部在同一个连接上几乎不变,但每次都要重复发送。一个大 Cookie 可能有 1-2KB,100 个请求就白白多传 100-200KB。

问题四:只能客户端主动

服务器不能主动给客户端推数据,只能客户端请求、服务器响应。想实现"服务器推送"只能用长轮询或 WebSocket。


五、HTTP/2(2015)------ 质的飞跃

核心思想

在一条 TCP 连接上实现真正的并行传输。

解决了什么

1. 二进制分帧(Binary Framing)------ 基础革新

HTTP/1.x 是文本协议(人能直接看懂),HTTP/2 改成了二进制协议。

所有数据被拆分成更小的 帧(Frame) ,每个帧有一个 Stream ID,标记它属于哪个请求/响应。

ruby 复制代码
HTTP/1.1(文本):
  GET /index.html HTTP/1.1\r\n
  Host: example.com\r\n
  \r\n

HTTP/2(二进制帧):
  ┌──────────┬───────────┬──────────────┐
  │ Length:9  │ Type:HEAD │ Stream ID: 1 │ HEADERS 帧
  ├──────────┴───────────┴──────────────┤
  │ :method = GET, :path = /index.html  │
  └─────────────────────────────────────┘

2. 多路复用(Multiplexing)------ 最重要的改进

多个请求/响应可以在同一个 TCP 连接上交错传输,互不阻塞。

ini 复制代码
HTTP/1.1:6 条连接,每条排队
  连接1: [请求1 ████████████]
  连接2: [请求2 ████]
  连接3: [请求3 ██████]
  连接4: [请求4 ███]
  连接5: [请求5 ████████]
  连接6: [请求6 ██]

HTTP/2:1 条连接,交错并行
  连接1: [帧1a][帧2a][帧3a][帧1b][帧2b][帧3b][帧1c][帧2c]...
          ↑stream1  ↑stream2  ↑stream3  ↑stream1  ↑stream2

类比理解:

HTTP/1.1 就像有 6 条单行道,每条道上车要排队。HTTP/2 就像有一条超宽的高速公路,所有车可以同时跑,通过车牌号(Stream ID)区分。

这彻底解决了 HTTP 层的队头阻塞,也不再需要"域名分片"等 hack 手段。

3. 头部压缩(HPACK)

HTTP/2 用 HPACK 算法压缩头部:

  • 维护一个静态表 (61 个常见头部,如 :method: GETcontent-type: text/html),用索引号代替完整字符串
  • 维护一个动态表,记录当前连接用过的头部,后续只发索引号
  • 对值做 Huffman 编码 压缩
ini 复制代码
第一次请求:
  Cookie: session=abc123def456...   (完整发送,同时存入动态表,索引 62)

第二次请求:
  62                                 (只发一个索引号,省掉了几百字节)

效果:头部大小减少 85-95%

4. 服务器推送(Server Push)

服务器可以主动推送客户端可能需要的资源。

bash 复制代码
客户端请求 /index.html
服务器响应 /index.html
服务器主动推送 /style.css   ← 不用等客户端解析 HTML 后再请求
服务器主动推送 /app.js      ← 提前到达,减少等待

但实际效果争议较大------很难准确预测客户端需要什么,推错了反而浪费带宽。Chrome 已在 2022 年移除了对 Server Push 的支持。

5. 流优先级(Stream Priority)

可以给不同的请求设置优先级。比如 CSS 优先级高于图片,因为 CSS 会阻塞渲染。

存在的问题

TCP 层的队头阻塞 ------ HTTP/2 的阿喀琉斯之踵

HTTP/2 解决了 HTTP 层的队头阻塞,但底下的 TCP 层还有队头阻塞

TCP 保证数据按序交付。如果一个 TCP 包丢失了,即使后面的包已经到达,TCP 也不会把它们交给应用层,而是等丢失的包重传回来。

arduino 复制代码
TCP 传输:包1 → 包2(丢了!) → 包3 → 包4 → 包5

TCP 层:包1 ✓   包2 ?等重传...  包3-5 已到但不能用
         └── 所有 Stream 都被阻塞!

HTTP/1.1 开 6 个连接,一个连接丢包只影响那一个连接上的请求。HTTP/2 所有请求共用一个连接,一个包丢失会阻塞所有请求

在网络质量差(丢包率 > 2%)的环境下,HTTP/2 的表现可能反而不如 HTTP/1.1

TLS 握手开销

HTTP/2 虽然协议本身不强制加密,但所有浏览器都要求 HTTP/2 必须走 HTTPS。TLS 握手需要额外的 1-2 个 RTT。


六、HTTP/3(2022)------ 换掉了 TCP

核心思想

既然 TCP 的队头阻塞无法在 TCP 层面解决,那就 不用 TCP 了 ,改用 QUIC(基于 UDP)。

QUIC 是什么

QUIC(Quick UDP Internet Connections)是 Google 设计的传输层协议,跑在 UDP 上。你可以把它理解为"重新实现了一个更好的 TCP"。

复制代码
HTTP/2 的协议栈:          HTTP/3 的协议栈:
┌──────────┐              ┌──────────┐
│  HTTP/2  │              │  HTTP/3  │
├──────────┤              ├──────────┤
│   TLS    │              │   QUIC   │ ← 把 TLS 融合进来了
├──────────┤              ├──────────┤
│   TCP    │              │   UDP    │
├──────────┤              ├──────────┤
│    IP    │              │    IP    │
└──────────┘              └──────────┘

解决了什么

1. 彻底消灭队头阻塞

QUIC 在传输层就支持多路复用。每个 Stream 独立管理自己的数据包顺序,一个 Stream 丢包不影响其他 Stream

arduino 复制代码
HTTP/2 + TCP:
  Stream 1 的包丢了 → 所有 Stream 被阻塞等重传

HTTP/3 + QUIC:
  Stream 1 的包丢了 → 只有 Stream 1 等重传,Stream 2/3/4 正常收发

2. 0-RTT 连接建立

TCP + TLS 需要的握手:

ini 复制代码
TCP 三次握手:   1 RTT(客户端→服务器→客户端)
TLS 1.2 握手:  2 RTT
TLS 1.3 握手:  1 RTT
──────────────────
总计:TCP + TLS 1.3 = 2 RTT(数据才能开始传)

QUIC 的握手:

复制代码
首次连接:1 RTT(QUIC 把传输层握手和加密握手合并了)
重连(0-RTT):0 RTT(第一个包就可以带数据!)

类比理解:

TCP + TLS 就像打电话:先拨号等接通(TCP),再输密码验证身份(TLS),然后才能说话。QUIC 就像发微信:直接把消息和身份验证一起发出去,对方收到就能回。重连时更像对方还认识你,直接开聊。

3. 连接迁移

TCP 连接用"源IP + 源端口 + 目标IP + 目标端口"四元组标识。你手机从 WiFi 切到 4G,IP 变了,TCP 连接就断了,必须重新握手。

QUIC 用一个 Connection ID 标识连接。IP 变了没关系,只要 Connection ID 不变,连接就能无缝切换。

ini 复制代码
TCP:WiFi → 4G = 连接断开 → 重新三次握手 + TLS 握手 → 恢复
QUIC:WiFi → 4G = IP 变了 → Connection ID 没变 → 无缝继续

对移动端体验提升巨大(电梯、地铁、从室内走到室外)。

4. 改进的头部压缩(QPACK)

HPACK 依赖严格的包顺序(因为动态表需要同步更新),和 QUIC 的乱序特性冲突。QPACK 解决了这个问题,允许在乱序到达的情况下也能正确解压头部。

存在的问题

问题 说明
UDP 被运营商/防火墙限制 部分网络环境会限速或丢弃 UDP 包,需要回退到 TCP
中间设备不友好 很多老旧的路由器、防火墙对 UDP 支持不好
CPU 开销 QUIC 在用户态实现(不在内核里),加解密和拥塞控制消耗更多 CPU
生态还在成熟 服务端支持(Nginx 2022 才正式支持)、调试工具都还在完善
无法利用 TCP 的内核优化 TCP 经过几十年优化,内核的 TCP 栈非常高效;QUIC 在用户态,暂时没法比

七、各版本一张图对比

scss 复制代码
        HTTP/0.9    HTTP/1.0    HTTP/1.1      HTTP/2        HTTP/3
年份      1991        1996        1997         2015          2022
传输层    TCP         TCP         TCP          TCP           UDP(QUIC)
连接方式  短连接      短连接      持久连接      多路复用       多路复用
并发能力  无          无          管线化(废了)   Stream并行     Stream并行
头部格式  无          文本        文本          HPACK压缩      QPACK压缩
加密      无          可选        可选          事实强制       强制(内置TLS)
队头阻塞  -           有          有(HTTP层)    有(TCP层)      无!
握手RTT   1(TCP)      1(TCP)      1(TCP)       2-3(TCP+TLS)  0-1(QUIC)
服务器推  无          无          无            支持(已废弃)    无

八、HTTPS 详解

8.1 为什么需要 HTTPS?

HTTP 是明文传输,存在三大安全风险:

风险 场景 后果
窃听 连公共 WiFi 时,路由器能看到所有内容 密码、银行卡号泄露
篡改 运营商在网页中插入广告 页面被注入恶意代码
冒充 钓鱼网站伪装成银行 用户被骗输入密码

HTTPS 就是 HTTP + TLS,用加密解决这三个问题:

安全需求 解决方案
防窃听 对称加密(AES),加密传输内容
防篡改 消息认证码(MAC),验证数据完整性
防冒充 数字证书 + 非对称加密(RSA/ECDSA),验证服务器身份

8.2 对称加密 vs 非对称加密

理解 HTTPS 之前,必须搞清楚这两种加密方式。

对称加密

加密和解密用同一把钥匙

bash 复制代码
明文 "Hello" + 密钥 K → 加密 → 密文 "x7$f2"
密文 "x7$f2" + 密钥 K → 解密 → 明文 "Hello"
  • 优点:速度快(AES 可达 GB/s 级别)
  • 缺点:密钥怎么安全地传给对方?如果密钥被截获,加密就白搭

常见算法:AES、ChaCha20

非对称加密

有两把钥匙:公钥 (公开)和 私钥(保密)。公钥加密的只有私钥能解,私钥加密的只有公钥能解。

复制代码
公钥加密:明文 + 公钥 → 密文(只有私钥能解)
私钥签名:数据 + 私钥 → 签名(公钥可验证)
  • 优点:不需要传递私钥,天然解决密钥分发问题
  • 缺点:速度极慢(比对称加密慢 100-1000 倍)

常见算法:RSA、ECDSA、Ed25519

HTTPS 的选择:混合加密

既然对称加密快但密钥分发难,非对称加密安全但太慢,那就结合使用

arduino 复制代码
① 用非对称加密安全地交换一个"临时密钥"(只需要一次,慢就慢吧)
② 之后所有数据都用这个临时密钥做对称加密(快!)

8.3 TLS 握手流程(TLS 1.2)

这是 HTTPS 最核心的部分------建立安全连接的过程。

arduino 复制代码
客户端                                              服务器
  │                                                    │
  │ ① ClientHello                                      │
  │    - 支持的 TLS 版本                                 │
  │    - 支持的加密套件列表                               │
  │    - 客户端随机数(Client Random)                    │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │                              ② ServerHello         │
  │    - 选定的 TLS 版本                                 │
  │    - 选定的加密套件                                   │
  │    - 服务器随机数(Server Random)                    │
  │                              ③ 服务器证书            │
  │                              ④ ServerHelloDone     │
  │ ◄─────────────────────────────────────────────────  │
  │                                                    │
  │ ⑤ 验证证书(证书链 → 根证书)                          │
  │ ⑥ 生成预主密钥(Pre-Master Secret)                  │
  │ ⑦ 用服务器公钥加密预主密钥                             │
  │ ⑧ ClientKeyExchange(发送加密后的预主密钥)            │
  │ ⑨ ChangeCipherSpec("我准备好了,之后都加密")         │
  │ ⑩ Finished(第一条加密消息)                          │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │                    ⑪ 用私钥解密得到预主密钥             │
  │                    ⑫ 双方各自计算会话密钥               │
  │                       = f(Client Random +           │
  │                          Server Random +            │
  │                          Pre-Master Secret)         │
  │                    ⑬ ChangeCipherSpec                │
  │                    ⑭ Finished                       │
  │ ◄─────────────────────────────────────────────────  │
  │                                                    │
  │ ═══════ 之后所有数据用会话密钥做对称加密 ═══════════    │

需要 2 个 RTT 才能开始传数据。

为什么要用三个随机数?

最终的会话密钥由三个随机数共同生成:

arduino 复制代码
会话密钥 = PRF(Pre-Master Secret, Client Random, Server Random)
  • Client Random:防止服务器重放攻击
  • Server Random:防止客户端重放攻击
  • Pre-Master Secret:只有双方知道的秘密(通过非对称加密安全交换)

三个随机数混合,即使其中一个被猜到,也无法推导出会话密钥。

8.4 TLS 1.3(2018)------ 更快更安全

TLS 1.3 是对 TLS 1.2 的大幅简化和优化。

主要改进

改进 TLS 1.2 TLS 1.3
握手 RTT 2 RTT 1 RTT(首次),0 RTT(重连)
密钥交换 RSA 或 ECDHE 只支持 ECDHE(前向安全)
加密套件 几十种 精简到 5 种
废弃的算法 - 砍掉 RC4、DES、3DES、MD5、SHA-1 等不安全算法
握手加密 握手过程明文 握手消息也加密(ServerHello 之后)

TLS 1.3 握手流程(只需 1 RTT)

复制代码
客户端                                              服务器
  │                                                    │
  │ ClientHello                                        │
  │    - 客户端随机数                                    │
  │    - 支持的加密套件                                   │
  │    - 客户端的 ECDHE 公钥 ← 关键!直接带上了            │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │                              ServerHello           │
  │                              + 服务器的 ECDHE 公钥   │
  │                              + 证书                 │
  │                              + Finished            │
  │ ◄─────────────────────────────────────────────────  │
  │                                                    │
  │ 双方用 ECDHE 算出相同的密钥                           │
  │ Finished                                           │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │ ═══════ 1 RTT 后就可以传数据了 ═══════════           │

为什么快了? 因为 TLS 1.2 客户端要等拿到服务器证书和公钥后才能开始密钥交换,而 TLS 1.3 客户端直接在 ClientHello 里就把自己的 ECDHE 公钥发出去了(赌服务器会接受),省了一个来回。

0-RTT 重连

如果之前连过这个服务器,客户端缓存了一个 PSK(Pre-Shared Key):

markdown 复制代码
客户端:ClientHello + PSK + 加密的应用数据 →
                                           服务器直接解密处理

第一个包就能带业务数据,延迟降到极致。

安全代价: 0-RTT 数据没有前向安全性,而且可能被重放攻击。所以只适合幂等请求(GET),不适合会产生副作用的操作(POST 转账)。

8.5 数字证书:怎么证明"你是你"

问题

非对称加密解决了"传密钥"的问题,但引入了新问题:你怎么知道拿到的公钥是真的?

中间人攻击:

复制代码
客户端 ←→ 中间人(伪装成服务器) ←→ 真正的服务器

中间人把自己的公钥发给客户端
客户端以为这是服务器的公钥,用它加密数据
中间人解密 → 看到明文 → 用服务器真正的公钥重新加密 → 发给服务器

解决:数字证书 + CA

引入一个双方都信任的第三方 ------ CA(Certificate Authority,证书颁发机构)

arduino 复制代码
① 服务器生成公私钥对
② 服务器把公钥 + 域名信息提交给 CA
③ CA 验证服务器确实拥有这个域名
④ CA 用自己的私钥对"服务器公钥 + 域名信息"做数字签名
⑤ CA 颁发证书(包含:服务器公钥 + 域名 + CA 签名 + 有效期等)
⑥ 客户端收到证书后,用 CA 的公钥验证签名
⑦ 签名正确 → 公钥可信 → 建立加密连接

类比理解:

就像你去政务大厅办事,需要身份证(证书)。身份证是公安局(CA)发的,上面有你的照片(公钥)和钢印(CA 签名)。办事员通过钢印确认身份证是真的,从而相信你就是本人。

证书链

CA 的公钥又是谁来保证的?答案是证书链

swift 复制代码
根证书(Root CA)        ← 预装在操作系统/浏览器中,无条件信任
  │
  └── 中间证书(Intermediate CA)  ← 根 CA 签发的
        │
        └── 服务器证书(End Entity)   ← 中间 CA 签发的

验证过程从下往上:

  1. 用中间 CA 的公钥验证服务器证书的签名
  2. 用根 CA 的公钥验证中间 CA 证书的签名
  3. 根 CA 证书在本地受信任列表中 → 整条链可信

为什么要分层?如果根 CA 直接签发所有证书,一旦根 CA 私钥泄露,后果不堪设想。分层后,即使中间 CA 出问题,只需要吊销这个中间 CA,不影响其他。

8.6 前向安全(Forward Secrecy)

问题

如果用 RSA 做密钥交换(TLS 1.2 的一种模式),一旦服务器私钥泄露,攻击者可以:

  1. 解密之前录制的所有流量中的 Pre-Master Secret
  2. 从而推导出所有历史会话密钥
  3. 所有历史通信全部暴露

解决:ECDHE 密钥交换

每次连接都生成临时的(Ephemeral) 公私钥对,用完即销毁。

css 复制代码
连接1:临时密钥对 A → 会话密钥 X → 销毁临时密钥对 A
连接2:临时密钥对 B → 会话密钥 Y → 销毁临时密钥对 B
连接3:临时密钥对 C → 会话密钥 Z → 销毁临时密钥对 C

即使服务器的长期私钥泄露,也无法解密之前的通信,因为临时密钥已经不存在了。

这就是"前向安全"(Forward Secrecy)。TLS 1.3 强制要求使用 ECDHE,所有连接都具有前向安全性。

8.7 HTTPS 的性能影响

开销 说明 缓解方案
握手延迟 TLS 1.2 多 2 RTT,TLS 1.3 多 1 RTT 升级 TLS 1.3、会话复用、0-RTT
加解密 CPU AES 加解密消耗 CPU 现代 CPU 都有 AES-NI 硬件加速,开销几乎可忽略
证书传输 证书链可能 3-5KB OCSP Stapling 减少验证开销
内存 每个连接需要维护加密上下文 影响很小

现代环境下 HTTPS 的额外开销已经非常小了,Google 的数据显示 HTTPS 只增加了不到 2% 的 CPU 负载和不到 10ms 的延迟。

8.8 常见 HTTPS 相关概念

概念 解释
HSTS 服务器告诉浏览器"以后只用 HTTPS 访问我",防止降级攻击
OCSP Stapling 服务器主动把证书有效性证明发给客户端,省去客户端向 CA 查询
CT(Certificate Transparency) 所有颁发的证书必须公开记录,防止 CA 偷偷签发恶意证书
SNI 客户端在 TLS 握手时告诉服务器要访问哪个域名(一个 IP 上多个 HTTPS 站点)
ESNI / ECH 加密 SNI,防止中间人知道你在访问哪个网站
证书固定(Pinning) App 内置预期的证书指纹,防止中间人使用合法但非预期的证书
Let's Encrypt 免费、自动化的 CA,推动了 HTTPS 的全面普及
双向认证(mTLS) 不仅服务器要证书,客户端也要证书(常见于企业内部、金融系统)

九、一张图总结

yaml 复制代码
1991  HTTP/0.9 ─── 只能传 HTML,连个状态码都没有
        │
1996  HTTP/1.0 ─── 有了头部、状态码、多媒体,但每次请求都要新建连接
        │
1997  HTTP/1.1 ─── 持久连接、缓存控制、断点续传,但有队头阻塞
        │             └── HTTPS(TLS 1.0~1.2) 解决安全问题
        │
2015  HTTP/2 ──── 二进制分帧、多路复用、头部压缩,但 TCP 层仍有队头阻塞
        │             └── TLS 1.3:1-RTT 握手、前向安全
        │
2022  HTTP/3 ──── 换用 QUIC(UDP),彻底消灭队头阻塞,0-RTT 连接,连接迁移

每一代都在解决上一代留下的问题,同时也带来了新的挑战。技术演进就是这样一步步往前走的。

相关推荐
忆江南2 小时前
对组件化与模块化的思考与总结
前端
小码哥_常2 小时前
从0到1:Android组件化架构搭建秘籍
前端
忆江南2 小时前
iOS 应用启动流程与优化详解
前端
itslife2 小时前
前端架构模式思考
前端·架构
Wect2 小时前
JSX & ReactElement 核心解析
前端·react.js·面试
雨落Re2 小时前
从递归组件到 DSL 引擎:我造了一个让 AI 能"搭 UI"的运行时
前端·vue.js
Maxkim2 小时前
前端工程化落地指南:pnpm workspace + Monorepo 核心用法与实践
前端·javascript·架构
大漠_w3cpluscom2 小时前
使用 clip-path: shape() 创建 Squircle 形状
前端·css·weui
大怪v14 小时前
AI抢饭?前端佬:我要验牌!
前端·人工智能·程序员