本系列的前几篇文章中,我们已经探讨了设备如何通过 IP 地址获得身份、如何通过 DNS 将域名解析为地址,以及如何通过 DHCP、NAT 和 VPN 等技术接入并穿梭于复杂的网络环境。至此,我们的设备已经具备了“定位”并“连接”到目标服务器的能力。

本文将深入探讨这个连接建立之后,应用程序之间进行通信所使用的“语言”——HTTP 协议,以及其安全版本 HTTPS。这两种协议构成了现代万维网的基石。

本系列其余几篇的目录:


前置知识说明:在阅读本文时,您会遇到 TCPUDP 这两个概念。它们是网络通信的两种基础“运输方式”,我们将在本系列的下一篇文章中深入探讨。为方便您理解本文,您可以暂时将它们想象为:

  • TCP:一种可靠的“电话通话”。在通话前,双方必须先建立连接,确保线路通畅,通话过程中能保证数据按顺序、不丢不漏地送达。
  • UDP:一种简单的“明信片”。它直接将数据包发出,不保证一定或按序到达,但胜在快捷高效。

本文中提到的 HTTP/1.1 和 HTTP/2 都构建在可靠的 TCP 之上,而最新的 HTTP/3 则创造性地选择了 UDP 作为基础。带着这个初步印象,您就可以顺利地理解下文内容了。

HTTP:构建 Web 的无状态协议

HTTP (HyperText Transfer Protocol,超文本传输协议) 是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维网数据通信的基础。

核心特性

  • 基于“请求-响应”模式:通信由客户端发起。客户端向服务器发送一个 HTTP 请求,服务器在处理后返回一个 HTTP 响应。
  • 无状态 (Stateless):协议本身不保存任何关于过去请求的信息。服务器处理每个请求时,都认为它是一个全新的、独立的事务,不依赖于之前的请求。您可以将它想象成一个记忆力很短的接待员,处理完你的当前请求后,立刻就会忘记你是谁。为了让它记住你,就需要 Cookies 这样的“身份牌”来帮忙。
  • 灵活可扩展:通过请求头和响应头,HTTP 允许传输任意类型的数据,不仅仅是 HTML,还包括图片、视频、JSON 等。其基础交互模型如下所示:

HTTP 报文结构

HTTP 通信由纯文本的报文(Message)组成,分为请求报文和响应报文。

不知道你有没有想过为什么“message”被翻译成了“报文”?其实是因为前辈们沿用了“电报”时代的相关概念,那时“报文”一词就已经蕴含了“通过电子信号传递的、有特定格式的文书”的意义。另外,“报”字蕴含了遵循协议的规范性,而“文”字则强调了其内容与格式的结构化,如同一份严谨的文书。所以最终这个概念的中文被译为了“报文”。
至于为何英语沿用通用的“message”而非更专业的词,是因为“message”本就是指代通信内容的基础词,而“telegraph”(电报)则指通信系统本身,而非内容单元。英语习惯用限定词(如 HTTP message)来明确上下文,无需替换基础词。这是两种语言在技术术语演变上的路径差异。

请求报文 (Request Message)

一个典型的 HTTP GET 请求报文结构如下:

GET /path/to/resource/index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...
Accept: text/html,*/*
Accept-Language: en-US,en;q=0.5

它由三部分构成:

  1. 请求行 (Request Line):包含请求方法(GET)、请求资源的路径(/path/...)和 HTTP 协议版本(HTTP/1.1)。
  2. 请求头 (Headers):以键值对形式提供关于请求的元数据,或客户端自身的信息。例如 Host 指定了目标服务器的域名,User-Agent 描述了客户端的类型。
  3. 请求体 (Body):对于 GET 请求,请求体为空。对于 POSTPUT 请求,这里会包含需要提交给服务器的数据,例如表单信息或 JSON 数据。

常见的请求方法(Method)有:

方法 描述
GET 请求获取指定资源。
POST 向指定资源提交数据,请求服务器进行处理(例如提交表单或上传文件)。
PUT 用请求中的数据体替换目标资源的全部当前内容。
DELETE 请求服务器删除指定的资源。
HEAD GET 类似,但服务器在响应中只返回头部,不返回实体主体内容。

响应报文 (Response Message)

服务器在收到并处理请求后,会返回一个响应报文:

HTTP/1.1 200 OK
Date: Mon, 18 Aug 2025 10:00:00 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 1270

<!DOCTYPE html>
<html>
...
</html>

它同样由三部分构成:

  1. 状态行 (Status Line):包含 HTTP 协议版本、状态码(200)和状态描述(OK)。
  2. 响应头 (Headers):提供关于响应的元数据,如 Content-Type 指明了响应体的媒体类型。
  3. 响应体 (Body):实际返回的资源内容,例如 HTML 文档。

状态码是服务器对请求处理结果的标准化表示,常见的有:

有一个很好玩的小网站分享给大家:https://http.cat/ ,用可爱的猫猫表示 HTTP 状态码。

状态码 名称 类别 描述
200 OK 成功 请求已成功。
201 Created 成功 请求成功,并因此创建了一个新的资源。
204 No Content 成功 服务器成功处理了请求,但没有返回任何内容。
301 Moved Permanently 重定向 请求的资源已被永久移动到新位置。
302 Found 重定向 请求的资源被临时重定向到另一个 URI。
304 Not Modified 重定向 用于缓存。表示资源未被修改,客户端可以继续使用已缓存的版本。
400 Bad Request 客户端错误 由于语法无效,服务器无法理解该请求。
401 Unauthorized 客户端错误 请求要求身份验证。客户端需要提供凭据。
403 Forbidden 客户端错误 服务器理解请求,但拒绝执行。与 401 不同,身份验证无法改变结果。
404 Not Found 客户端错误 服务器找不到请求的资源。
405 Method Not Allowed 客户端错误 服务器知道请求的方法,但目标资源不支持该方法。
429 Too Many Requests 客户端错误 用户在给定的时间内发送了太多的请求(速率限制)。
500 Internal Server Error 服务器错误 服务器遇到了一个未曾预料的状况,导致其无法完成对请求的处理。
502 Bad Gateway 服务器错误 作为网关或代理的服务器,从上游服务器收到了无效的响应。
503 Service Unavailable 服务器错误 服务器当前无法处理请求(由于超载或停机维护)。

为了更直观地对比,下表总结了请求报文与响应报文的核心区别:

构成部分 请求报文 (Request) 响应报文 (Response)
起始
(行)
格式:方法 URI HTTP版本
示例:GET /index.html HTTP/1.1
格式:HTTP版本 状态码 描述
示例:HTTP/1.1 200 OK
首部
(头)
描述客户端信息、请求的资源等。
示例:Host, User-Agent
描述服务器信息、返回内容的类型等。
示例:Content-Type, Server
正文
(体)
通常用于 POST 等方法,携带提交给服务器的数据。GET 请求通常为空。 包含返回给客户端的实际资源内容,如 HTML 文档、JSON 数据等。

HTTP 的版本演进与协商机制

HTTP 协议并非一成不变,它在过去几十年中经历了数次重要迭代,以适应日益复杂的 Web 应用和用户对性能的更高要求。

HTTP/1.0 与 HTTP/1.1

  • HTTP/1.0 (1996):作为早期版本,其主要特点是短连接。每次请求都需要建立一个新的 TCP 连接,请求完成后立即断开,效率低下。
  • HTTP/1.1 (1999):这是统治了互联网近 20 年的经典版本。它最重要的改进是引入了持久连接(Keep-Alive),允许在同一个 TCP 连接上发送多个请求,极大地减少了连接建立的开销。但它也存在一个著名的问题——队头阻塞(Head-of-Line Blocking),即在一个连接上,前一个请求的响应必须完全接收后,后续的请求才能被处理,导致效率瓶颈。

HTTP/2 (2015)

HTTP/2 的目标是彻底解决 HTTP/1.1 的性能问题,其核心改进包括:

  • 二进制分帧:将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式编码,解析效率更高。
  • 多路复用 (Multiplexing):这是 HTTP/2 最具革命性的特性。它允许在单个 TCP 连接上同时、并行地发送和接收多个请求和响应,彻底解决了队头阻塞问题。
  • 头部压缩 (HPACK):使用特定算法压缩冗余的请求头和响应头,减少了传输的数据量。

HTTP/3 (2022)

HTTP/3 的演进更进一步,它将底层的传输协议从 TCP 换成了 QUIC

  • 基于 QUIC:QUIC 是一个基于 UDP 的新传输协议,它整合了 TCP 的可靠性、TLS 的安全性以及更多新特性。
  • 解决 TCP 队头阻塞:HTTP/2 虽然解决了应用层的队头阻塞,但无法解决 TCP 协议本身的队头阻塞(一个数据包丢失,整个连接都要等待重传)。QUIC 基于 UDP,一个流的丢包不会影响其他流,从根本上解决了这个问题。
  • 更快的连接建立:QUIC 将 TCP 和 TLS 的握手过程合并,减少了建立连接所需的往返时间(RTT),让连接更快。

版本协商:客户端与服务器如何“对暗号”?

既然有这么多版本,客户端和服务器是如何确定使用哪个版本的呢?这个过程被称为协议协商

  • HTTP/2 的协商:这是一个有趣的地方。虽然 HTTP/2 的协议规范本身并不强制加密(存在明文的 h2c 模式),但所有主流浏览器都达成了一个共识:只支持通过 HTTPS 运行的 HTTP/2。这既是为了推动全网加密,也是为了绕过可能不支持新协议的旧网络设备。因此,在浏览器实践中,HTTP/2 的协商几乎总是通过 TLS 的一个扩展 ALPN (Application-Layer Protocol Negotiation) 来实现。在 TLS 握手时,客户端会告诉服务器它支持的协议列表(如 ["h2", "http/1.1"]),服务器则从中选择一个它也支持的最高版本,并在 TLS 握手完成时通知客户端。
  • HTTP/3 的协商:由于 HTTP/3 运行在不同的协议(UDP)上,它的发现机制有所不同。通常,服务器会通过 HTTP/1.1 或 HTTP/2 的响应头 Alt-Svc (Alternative Service) 来“广播”自己的 HTTP/3 服务地址。例如,Alt-Svc: h3=":443"。浏览器收到后,就会尝试在后台建立一个到该地址的 QUIC 连接,并在后续请求中升级到 HTTP/3。

HTTPS:为对话加上安全封印

HTTP 协议本身是明文传输的,这意味着任何在传输路径上的中间节点(如路由器、ISP)都能轻易地读取、甚至篡改通信内容。这带来了三大安全风险:

  • 窃听风险 (Eavesdropping):通信内容可能被第三方窃听。
  • 篡改风险 (Tampering):通信内容在传输过程中可能被修改。
  • 冒充风险 (Impersonation):无法验证通信对方的真实身份,可能连接到伪造的服务器。

为了解决这些问题,HTTPS (HTTP Secure) 应运而生。

HTTPS 的核心

HTTPS 并非一个全新的协议,它的结构是 HTTPS = HTTP + TLS/SSL。它在标准的 HTTP 应用层和 TCP 传输层之间,增加了一个加密、认证和完整性保护的 TLS/SSL 安全层

SSL (Secure Sockets Layer) 是 TLS (Transport Layer Security) 的前身,由于存在安全漏洞现已弃用。
我们目前实际使用的都是 TLS 协议,但出于历史习惯,人们常将二者并称为 TLS/SSL。

这个安全层主要提供三大核心安全保障:

  1. 加密 (Encryption):确保通信内容无法被窃听。有趣的是,这里使用的是对称加密。因为非对称加密虽然更灵活,但计算开销巨大,速度过慢,不适合加密海量的应用数据。而对称加密速度极快,正适合此场景。
  2. 身份验证 (Authentication):通过数字证书,客户端可以验证服务器的身份,确保连接到的是预期的、真实的服务器,防止冒充。
  3. 数据完整性 (Integrity):通过消息认证码(MAC),确保数据在传输过程中没有被篡改。

TLS 握手机制

当浏览器访问一个 HTTPS 网站时,在真正发送 HTTP 请求之前,它必须先与服务器完成一次 TLS 握手,以建立一个安全的信道。这个过程在概念上可以分为几个步骤,其交互流程可通过以下序列图来描述:

  1. 客户端问候 (Client Hello):客户端向服务器发起连接,并发送它支持的加密算法列表、TLS 版本等信息。
  2. 服务器响应与身份证明 (Server Hello & Certificate):服务器从中选择一套双方都支持的加密算法,然后将其数字证书(包含了服务器的公钥和由权威证书颁发机构 CA 的签名)发送给客户端。
  3. 客户端验证与密钥交换(非对称加密的应用)
    • 客户端验证服务器证书的有效性(是否由受信任的 CA 签发、是否过期、域名是否匹配等)。
    • 验证通过后,客户端生成一个用于本次会话的“暗号”(pre-master secret),然后使用从证书中获取的服务器公钥对其进行加密(非对称加密),并发送给服务器。
  4. 生成会话密钥与建立安全信道:服务器使用自己的私钥解密,是全网唯一能获取该“暗号”的实体。随后,客户端和服务器使用这个共享的“暗号”,通过相同的算法,各自生成出完全一样的对称会话密钥。握手完成。
  5. 安全通信:后续所有的 HTTP 数据都将使用这个对称密钥进行加密和解密,实现安全的通信。

在这个流程中,非对称加密(公钥/私钥)被巧妙地用于安全地协商和交换对称加密所使用的密钥,兼顾了安全性和性能。这就像用一把非常复杂、开锁很慢但无法被复制的钥匙(非对称加密),去打开一个保险箱,从里面取出一把开门又快又方便的普通钥匙(对称加密),然后锁上保险箱,以后进出都用这把普通钥匙。

TLS 握手与“三次握手”的区别

需要明确的是,TLS 握手不是我们常说的 TCP“三次握手”。这是一个非常常见但重要的混淆点,它们是两个发生在不同阶段、目的也完全不同的过程:

  • 三次握手 (TCP Handshake):发生在传输层,目的是建立一个可靠的通信连接,确保双方都准备好了收发数据。它不关心内容是否加密。
  • TLS 握手 (TLS Handshake):发生在 TCP 连接建立之后,目的是在已有的可靠连接上,再建立一个安全的加密信道,协商后续通信要使用的加密密钥。

简单来说,先有 TCP 三次握手建立起“物理通话线路”,再有 TLS 握手在这条线路上约定“加密暗号”。

融会贯通:连接系列知识

HTTP/HTTPS 作为应用层协议,其运行离不开底层网络设施的支持。

  • 协议、端口与 DNS 的协同工作:在第二篇文章中我们了解到,URL https://www.example.com 中的 https 部分,正是告诉浏览器需要通过 443 端口(回顾第一篇)连接到由 DNS 解析出的 IP 地址,并启动上文所述的 TLS 握手流程。

  • 应用层加密与网络层加密:HTTPS vs. WireGuard:在第四篇文章中,我们深入了 WireGuard。现在可以清晰地对比二者的区别:

    • HTTPS应用层工作,它保护的是单个应用程序(如浏览器)与单个目标服务器之间的通信内容。它不关心数据包如何路由,只关心应用数据的安全。
    • WireGuard网络层工作,它保护的是设备VPN 服务器之间的所有 IP 流量。一旦连接,无论是 HTTP 请求、DNS 查询还是其他任何网络活动,都会被封装在加密隧道中。它提供的是全面的网络链路级安全。

总结

HTTP 定义了 Web 内容交换的基本规则,而 HTTPS 则为其增加了至关重要的安全保障。理解这两种协议的原理、结构以及它们在整个网络协议栈中的位置,是理解现代互联网运作方式的关键。它们与底层的 IP、DNS、TCP/UDP 等协议协同工作,共同构成了我们每天都在使用的、复杂而又高效的全球信息网络。