超文本传输协议(HTTP)是一个允许 Web 浏览器与 Web 服务器(储存网站的位置)进行通信的消息传输协议。
一、 概述
HTTP(Hypertext Transfer Protocol)是一种获取诸如 HTML 文档这类资源的应用层协议,通过 TCP 或 TLS 来发送。
客户端与服务器之间交换一个个独立的消息进行通信。由客户端发出的消息称作请求(request),由服务端发出的应答消息被称为响应(response)。
二、 基本性质
- 简约的:HTTP 被设计得简单且易读,尽然在 HTTP2 中,HTTP 消息被封装进帧(frame)这点引入了额外的复杂度。HTTP 报文能够被人读懂且理解
- 可扩展的:只要服务器客户端之间对新标头的语义经过简单协商,新功能就可以被加进来
- 无状态并非无会话:可以借助于 HTTP Cookie 就可以使用有状态的的会话。利用标头的扩展性,HTTP Cookie 被加进了协议工作流程,每个请求之间就能够建立会话,让每一个请求能够共享相同的上下文和相同的状态
三、 HTTP 能控制什么
- 缓存:文档如何被缓存可以通过 HTTP 来控制。服务器能指示代理和客户端之间缓存那些内容以及缓存多长时间,客户端能够指示中间的缓存代理来忽略已储存的文档
- 同源限制:为了阻止网络窥探和其它侵犯隐私的问题,Web 浏览器强制进行了同源限制
- 认证:基本的认证可以直接由 HTTP 提供,即可以使用 WWW-Authenticate 或其他类似的标头,也可以用 HTTP cookie 来设置一个特定的会话
- 代理:服务器或客户端常常处于内网的,对其他计算机隐藏真实 IP 地址。因此请求就要通过代理服务器越过这个网络屏障。并非所有的代理都是 HTTP 代理,例如, SOCKS 协议就是运作在更底层
- 会话:使用 HTTP Cookie 可以利用服务端的状态讲不同的请求联系起来。
四、 HTTP 流
信息交互时:
-
- 开发一个 TCP 连接:TCP 连接被用来发送一条或多条请求,以及接受响应消息。客户端可能打开一条新的连接,或者复用已经存在的连接,或者也可能打开几个新的和服务器之间的连接
-
- 发一个 HTTP 报文:HTTP 报文(在 HTTP/2 之前)是可读的
-
- 读取服务器返回的报文信息
-
- 关闭连接或者为后续请求重用连接
五、 报文
HTTP/1.1 以及之前更早的 HTTP 协议报文都是语义可读的。在 HTTP/2 中,这些报文被嵌入到了一个新的二进制结构--帧。帧允许很多的优化,比如报文标头的压缩和多路复用。
有两种 HTTP 报文的类型,请求与响应,每种都有其特定的格式。
1. 请求报文
- HTTP 方法:通常有一个动词,像
GET、POST等,或者一个名词,像OPTIONS、HEAD等,来定义客户端要执行的动作。 - 获取资源的路径:取出当前上下文显而易见的信息之后的 URL,它不包括协议(
https://)、域名(earthnut.dev),或是 TCP 的端口(443) - HTTP 协议版本号
- 为服务器表达其他信息的的可选标头
- ** 请求体**
2. 响应报文
- HTTP 协议版本号
- 状态码:指明对应请求已成功执行与否,以及不成功响应的原因
- 状态信息:这个信息是一个不权威、简短的状态码描述
- HTTP 标头:与请求标头类似
- 可选项:一个包含被请求资源的主体
三、 HTTP 版本之间差异
HTTP 2 通过二进制分帧和多路复用解决了 HTTP 1.1 的队头阻塞,但依赖 TCP (存在 TCP 层队头阻塞);HTTP 3 基于 UDP 的 QUIC 协议,彻底解决了队头阻塞,同时优化了连接建立速度和迁移能力。
| 特性 | HTTP1.1(1999) | HTTP 2 (2015) | HTTP 3 (2022,基于 QUIC) |
|---|---|---|---|
| 传输层协议 | TCP | TCP | UDP(基于 QUIC 协议) |
| 协议格式 | 文本协议(易读,但冗余) | 二进制分帧(高效,不可读) | 二进制分帧(基于 QUIC 结构) |
| 队头阻塞 | ❌(同一连接,请求需排队) | ✅(多路复用,并行处理请求) | ✅(QUIC 单个阻塞不影响其他流) |
| 多路复用 | ❌(需多连接或串行) | ✅(同一连接并行传输多个请求/响应) | ✅(QUIC 原生多路复用) |
| 头部压缩 | ❌(重复头部冗余) | ✅(HPACK 算法,减少头部传输量) | ✅(QPACK,基于 HPACK 优化) |
| 服务器推送 | ❌ | ✅(主动推送关联资源,如 HTML + CSS) | ✅(基于 QUIC 的流推送) |
| 连接建立速度 | 慢( TCP 三次握手) | 慢(TCP 三次握手) | 快(0-RTT/1-RTT 建立,减少握手耗时) |
| 连接迁移 | ❌(切换网络需重连) | ❌ | ✅(基于连接 ID ,切换网络不中断) |
| 加密 | 需配合 HTTPS | 强制使用加密(QPACK 压缩) | |
| 应用场景 | 适用于静态内容发布,但并发曾经受限 | 支持动态内容发布 (如视频流) | 实时通信和高延迟网络(如移动端) |
各版本握手区别
- HTTP/1.0:默认每个资源独立建立 TCP 连接(短连接),需为每一个资源单独三次握手和四次挥手(效率低)
- HTTP/1.1:默认启用长连接(Persistent Connection),多个资源可复用同一个 TCP 连接(仅需一次三次握手和四次挥手)
- HTTP/2/3:进一步优化,通过多路复用(Multiplexing)在单个连接上并行处理多个资源,无需为每个资源新建连接
1. HTTP/1.0:短连接为主
HTTP/1.0 时代,浏览器与服务器的默认行为时每个资源请求都新建 TCP 连接:
-
加载一个包含 HTML、CSS、JS、图片的网页时,每个资源都会触发一次 TCP 三次握手建立连接,传输完成后通过四次挥手关闭连接
-
缺点:频繁的三次握手和四次挥手会增加延迟(尤其是弱网环境),且大量占用服务器和客户端的连接资源
2. HTTP/1.1:长连接(Persistent Connection)
HTTP/1.1 引入 Connection: keep-alive 头(默认启用),允许在一个 TCP 连接上发送多个资源请求 。减少了重复握手的开销,但受限于浏览器的并发连接数限制(如 Chrome 对同一域名默认最多为 6 个并发连接)。若资源超过并发数,后续资源需等到已有连接释放后再发送。
- 浏览器加载网页时,先通过三次握手建立 TCP 连接,然后依次发动 HTML、CSS、JS 等资源的请求(无需为每一个资源重新握手)
- 所有资源传输完毕后,客户端或服务器通过
Connection: close头或超时机制触发四次挥手关闭连接
3. HTTP/2:多路复用(Multiplexing)
HTTP/2 基于 TLS 加密(默认),核心特性是多路复用。彻底解决了 HTTP/1.1 的对头阻塞(Head-of-Line Blocking)问题,大幅提升了加载效率
- 浏览器与服务器建立一个 TCP 连接,但通过二进制分帧(Binary Framing)将多个请求/响应拆分为独立的“帧”(Frame),并行传输
- 所有的资源(HTML、CSS、JS、图片等)共享一个 TCP 连接,无需为每一个资源单独握手或挥手
HTTP/2 还引入了头部压缩(HPACK)和请求优先级,进一步优化传输效率
4. HTTP/3 基于 QUIC 的多路复用
HTTP/3 放弃 TCP,该用 QUIC 协议(基于 UDP):
- 每个域名对应一个 QUIC 连接(通过 UDP 端口 443 或其他),所有资源请求通过该连接的多路复用传输
- QUIC 内置加密和连接管理,无需 TCP 三次握手和四次挥手(QUIC 连接建立更快,且支持快速连接)
- 0-RRT 握手:QUIC 支持 0-RTT(零往返时间)握手,客户端无需等待服务器响应即可发送加密数据,进一步减少延迟
- 多路复用与连接迁移:QUIC 天然支持多路复用,且连接 ID 独立于 IP 和端口,允许客户端在网络切换(如 WIFI 到 4G)时保持连接不断