TCP、HTTP协议的深入研究

cuixiaogang

底层基础知识

通信模式

在计算机通信领域中,常见的模型默认有三种:单工模式、半双工模式、全双工模式

单工模式(Simplex)

  • 定义:数据只能沿一个方向传输,一方固定为发送端,另一方固定为接收端,无法反向通信。
  • 特点:信道是单向的,无需考虑双向同步或冲突问题,结构简单但灵活性低。
  • 举例:广播电视(电视台发送信号,电视机只能接收)、键盘向电脑输入数据(键盘仅发送,电脑仅接收)、打印机接收电脑指令(打印机仅接收)。

半双工模式(Half-Duplex)

  • 定义:数据可以双向传输,但同一时间内只能沿一个方向传输,即发送和接收不能同时进行,需要交替切换方向。
  • 特点:共享同一信道,通信双方需要协商切换方向,可能存在一定的延迟(如等待对方释放信道)。
  • 举例:对讲机(一方说话时另一方需等待,按下 “说话键” 时只能发送,松开后才能接收)、早期的以太网(使用同轴电缆时,同一时间只能有一台设备发送数据,避免冲突)、无线电报。

全双工模式(Full-Duplex)

  • 定义:通信双方(或设备)可以在同一时间内同时发送和接收数据,即双向通信可并行进行,无需等待对方停止发送。
  • 特点:需要两条独立的物理信道,分别负责“发送”和“接手”,并且发送和接收的操作可以同时进行。
  • 举例:电话通话、现代以太网、即时视频通话、光纤通信

OSI七层模型与TCP/IP四层模型

OSI七层模型

OSI即开放式互联,该体系定义了网络互联的七层框架。OSI参考模型是一个具有七层结构的模型,发送和接收信息所涉及的内容和相应的设备称为实体,OSI的每一层都包含多个实体,处于同一层的实体称为对等实体。

七层协议(快速记忆法):物(物理层 Physical)、数(数据链路层 Data Link)、网(网络层 Network)、传(传输层 Transport)、会(会话层 Session)、表(表示层 Presentation)、应(应用层 Application)

image.png

TCP/IP四层概念模型

TCP/IP四层概念模型是对OSI七层模型的简化与优化,它参照OSI模型的分层概念,将一些功能相近的层进行了合并,最终形成的结果如下:

image.png

TCP/IP协议

TCP 提供面向有连接的通信传输,面向有连接是指在传送数据之前必须先建立连接,数据传送完成后要释放连接。

无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过三次握手进行初始化的。同时由于TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议,TCP是全双工模式,所以需要四次挥手关闭连接。

TCP协议在网络模型中的位置

TCP 属于传输层协议,在不同网络模型中的定位如下:

  • OSI 七层模型:位于第 4 层(传输层),下方依赖网络层(如 IP 协议)提供的主机到主机的分组传输服务,上方为应用层协议(如 HTTP、FTP、SMTP 等)提供可靠的数据传输支持。
  • TCP/IP 四层模型:同样位于第 4 层(传输层),与 OSI 模型的传输层功能一致,是 TCP/IP 协议栈的核心协议之一(另一核心是网络层的 IP 协议)。

TCP报文格式

TCP 报文(段,Segment)由首部和数据部分组成,首部最小长度为 20 字节,最大为 60 字节(含选项字段)。

image.png

image.png

字段 长度(字节) 作用说明
源端口 2 发送端的端口号,用于标识发送进程。
目的端口 2 接收端的端口号,用于标识接收进程。
序列号 4 对发送的字节流编号(按字节计数),用于保证数据有序性和去重(如首次发送 SYN 时,序列号为初始 ISN)。
确认号 4 期望收到的下一字节的序列号(仅当 ACK=1 时有效),用于确认已收到的数据。
数据偏移 4 位(0.5 字节) 表示 TCP 首部长度(单位:32 位字,即 4 字节),用于区分首部和数据部分(最小值为 5,对应 20 字节)。
保留位 6 位 预留未使用,通常为 0。
控制位 6 位 共 6 个标志位,分别为:
- URG:紧急指针有效;
- ACK:确认号有效(握手 / 挥手核心);
- PSH:立即推送数据给应用层;
- RST:重置连接(用于错误恢复);
- SYN:同步序列号(用于建立连接);
- FIN:终止连接(用于关闭连接)。
窗口大小 2 接收窗口大小,用于流量控制(告知对方自己的接收缓冲区剩余容量)。
校验和 2 用于校验整个 TCP 报文(首部 + 数据)的完整性,检测传输错误。
紧急指针 2 当 URG=1 时有效,指示紧急数据在数据部分中的偏移量(优先传输紧急数据)。
选项(可选) 0~40 用于扩展 TCP 功能(如最大报文段长度 MSS、窗口扩大因子、时间戳等)。
数据部分 可变 应用层传递的实际数据(长度受 MSS 限制,避免 IP 分片)。

TCP 三次握手(建立连接)

TCP 是面向连接的协议,通信前必须通过 “三次握手” 建立可靠连接。核心目的是:同步双方的初始序列号(ISN)、确认双方的收发能力。

详细过程如下

  • 第一次握手(客户端→服务端)
    • 客户端主动发起连接,发送报文:SYN=1(同步标志),seq=x(客户端初始序列号 ISN_c)。
    • 客户端状态:从CLOSED→SYN_SENT。
  • 第二次握手(服务端→客户端)
    • 服务端收到 SYN 后,同意连接,回复报文:SYN=1(同步标志),ACK=1(确认标志),seq=y(服务端初始序列号 ISN_s),ack=x+1(确认已收到客户端的 x,期望下一字节为 x+1)。
    • 服务端状态:从LISTEN→SYN_RCVD。
  • 第三次握手(客户端→服务端)
    • 客户端收到 SYN+ACK 后,发送报文:ACK=1,seq=x+1(客户端序列号递增),ack=y+1(确认已收到服务端的 y,期望下一字节为 y+1)。
    • 客户端状态:从SYN_SENT→ESTABLISHED;服务端收到后状态:从SYN_RCVD→ESTABLISHED。

三次握手可确保双方 “发送能力” 和 “接收能力” 均正常,且序列号同步完成。

image.png

TCP 四次挥手(终止连接)

TCP 连接是全双工的,关闭时需双方分别终止各自的发送方向,因此需要 “四次挥手”。

详细过程如下

  • 第一次挥手(客户端→服务端)
    • 客户端主动关闭连接,发送报文:FIN=1(终止标志),seq=u(客户端当前序列号)。
    • 客户端状态:从ESTABLISHED→FIN_WAIT_1(等待服务端确认)。
  • 第二次挥手(服务端→客户端)
    • 服务端收到 FIN 后,回复确认:ACK=1,seq=v(服务端当前序列号),ack=u+1(确认已收到客户端的 FIN)。
    • 此时客户端到服务端的方向关闭,但服务端仍可向客户端发送数据;服务端状态:从ESTABLISHED→CLOSE_WAIT;客户端状态:从FIN_WAIT_1→FIN_WAIT_2(等待服务端的 FIN)。
  • 第三次挥手(服务端→客户端)
    • 服务端完成数据发送后,主动关闭自己的发送方向,发送报文:FIN=1,ACK=1,seq=w(服务端当前序列号),ack=u+1。
    • 服务端状态:从CLOSE_WAIT→LAST_ACK(等待客户端确认)。
  • 第四次挥手(客户端→服务端)
    • 客户端收到 FIN 后,回复确认:ACK=1,seq=u+1,ack=w+1。
    • 客户端状态:从FIN_WAIT_2→TIME_WAIT(等待 2MSL,确保服务端收到确认);服务端收到后状态:从LAST_ACK→CLOSED。
    • 客户端等待 2MSL(报文最大生存时间)后,状态从TIME_WAIT→CLOSED。

关闭连接时,双方需各自终止发送方向。服务端收到 FIN 后,可能还有数据未发送,因此先回复 ACK(第二次挥手),待数据发送完毕后再发 FIN(第三次挥手),故无法合并为三次。

image.png

HTTP协议概述与发展历程

HTTP(HyperText Transfer Protocol)是互联网上应用最为广泛的网络协议,用于客户端和服务器之间的通信。自1996年HTTP/1.0发布以来,HTTP协议经历了多次重大升级,其中HTTP/1.1成为了长期稳定的版本,而HTTP/2则是在2015年正式发布的重大升级版本。

HTTP协议的核心特点是请求-响应模型,客户端发起请求,服务器返回响应。随着互联网内容的日益丰富和复杂,对HTTP协议的性能要求也越来越高。HTTP/2正是为了解决HTTP/1.x的性能瓶颈而设计的。

HTTP/1.x系列协议

HTTP/1.x系列协议包括HTTP/1.0和HTTP/1.1,其中HTTP/1.1于1999年发布,是目前使用最广泛的HTTP版本。HTTP/1.1引入了持久连接、管道化等重要特性,显著提升了HTTP协议的性能。

HTTP/2的诞生背景

随着Web应用的复杂化,HTTP/1.x的性能瓶颈逐渐显现:

  • 队头阻塞问题:在同一TCP连接上,如果一个请求处理缓慢,后续请求必须等待,造成性能下降。
  • 头部冗余:每个请求都需要重复发送相似的头部字段,浪费带宽。
  • 二进制协议缺失:文本格式的协议解析效率低,且难以实现高级功能。

HTTP/2正是为了解决这些问题而设计的,它基于Google的SPDY协议,于2015年以RFC 7540正式发布。

HTTP/1.x系列协议

HTTP/1.x系列的工作原理与数据流转

HTTP/1.0(短连接模式)

在短连接模式下,每个请求/响应都需要建立一个新的TCP连接:

  • 客户端与服务器建立TCP连接(三次握手)
  • 客户端发送请求报文
  • 服务器返回响应报文
  • 连接关闭(四次挥手)

这种模式的缺点是连接建立和关闭开销大,特别是在请求频繁的情况下,性能会显著下降。

HTTP/1.1(持久连接)

HTTP/1.1引入了持久连接(Persistent Connection),通过在请求头中添加Connection: keep-alive,允许在同一个TCP连接上发送多个请求/响应:

  • 客户端与服务器建立TCP连接
  • 客户端发送多个请求,服务器依次返回响应
  • 所有请求处理完毕后,连接可以保持一段时间,供后续请求使用

持久连接减少了TCP连接建立和关闭的开销,但仍然存在队头阻塞问题——当前一个请求未完成时,后续请求必须等待。

管道化(Pipelining)

HTTP/1.1还引入了管道化(Pipelining)技术,允许在未收到前一个响应的情况下发送下一个请求:

  • 客户端在一个TCP连接上连续发送多个请求
  • 服务器按顺序返回响应

然而,管道化在实际应用中并未得到广泛支持,主要原因是它仍然无法解决队头阻塞问题,且实现复杂度高。

HTTP/1的请求-响应模型及报文格式

HTTP/1采用严格的请求-响应模型,客户端必须等待前一个请求的响应完全接收后才能发送下一个请求(除非使用管道化)。

请求报文结构

HTTP/1请求报文由四个部分组成:

  • 请求行
  • 头部字段
  • 空行
  • 请求体(可选)

请求行格式与示例:

1
2
3
4
方法 URI HTTP版本

// 示例
GET /index.html HTTP/1.1

头部字段是键值对形式,用于传递附加信息,比如:

1
2
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

响应报文结构

HTTP/1响应报文同样由四个部分组成:

  • 状态行
  • 头部字段
  • 空行
  • 响应体(可选)

状态行格式与示例:

1
2
3
4
HTTP版本 状态码 原因短语

// 示例
HTTP/1.1 200 OK

HTTP/1的数据流转方式

HTTP/1的数据流转基于文本格式,采用串行传输方式:

  1. 客户端与服务器建立TCP连接
  2. 客户端将请求报文转换为文本字符串,通过TCP连接发送
  3. 服务器接收文本字符串,解析出请求内容
  4. 服务器处理请求,生成响应报文
  5. 服务器将响应报文转换为文本字符串,通过TCP连接发送
  6. 客户端接收文本字符串,解析出响应内容
  7. 连接关闭(短连接)或保持(持久连接)

这种方式的主要问题在于:

  • 文本格式效率低:文本解析需要额外处理,且头部字段重复传输
  • 队头阻塞:同一连接上的请求必须按顺序处理
  • 连接利用率低:每个连接同一时间只能处理一个请求

HTTP/2协议

HTTP/2 是 HTTP 协议的重大升级,它保留了 HTTP/1 的语义,但在底层传输机制上进行了革命性改进。

核心特性

二进制分帧层

HTTP/2摒弃了HTTP/1的文本格式,转而采用二进制分帧层(Binary Framing Layer):

  • 将整个通信分解为帧(Frame)的交换
  • 每个帧携带特定类型的数据(如头部、正文、设置等)
  • 帧是最小的传输单位,通过流标识符(Stream ID)关联到特定的流

image.png

image.png

上图分别是HTTP1.1与HTTP2.0的构造图,从这两张图可以看出,HTTP1.1是明文文本,而 HTTP2.0首部(HEADERS)和数据消息主体(DATA)都是帧(frame)。frame是HTTP2协议中最小数据传输单元。

帧(frame)主要组成部分如下:

  • 帧头(Headers Frame):固定的9个字节
    • 长度(Length):无符号的自然数,24个比特表示,仅表示帧负载(Frame Payload)所占用字节数,不包括帧头所占用的9个字节。 默认大小区间为为0~16,384(2^14),一旦超过默认最大值2^14(16384),发送方将不再允许发送,除非接收到接收方定义的
    • 类型(Type):8个比特表示,定义了帧负载的具体格式和帧的语义,HTTP/2规范定义了10个帧类型,这里不包括实验类型帧和扩展类型帧,常见类型如下:
      • 0x0:DATA 帧(传输流的核心内容)
      • 0x1:HEADERS 帧(包含 HTTP 首部)
      • 0x2:PRIORITY 帧(指示或更改流的优先级)
      • 0x3:RST_STREAM 帧(停止流)
      • 0x4:SETTINGS 帧(协商连接级参数)
      • 0x5:PUSH_PROMISE 帧(服务器推送)
      • 0x6:PING 帧(测试连接可用性)
      • 0x7:GOAWAY 帧(结束连接)
      • 0x8:WINDOW_UPDATE 帧(流量控制)
      • 0x9:CONTINUATION 帧(扩展 HEADERS 数据块)
    • 标记(Flags):8个比特表示,具体含义由帧类型决定。
      • DATA 帧的 END_STREAM 标志(位 0):表示该帧是流的最后一个帧。
      • HEADERS 帧的 PADDED 标志(位 3):表示帧包含填充数据。
    • R:1个比特表示,保留位,必须设置为 0。非 0 值会导致协议错误(PROTOCOL_ERROR)。
    • 流标识(Stream Identifier):无符号的31比特表示,无符号自然数。0x0值表示为帧仅作用于连接,不隶属于单独的流。遵循如下规则:
      • 客户端发起的流 ID 为奇数(如 1, 3, 5…)。
      • 服务端发起的流 ID 为偶数(如 2, 4, 6…)。
      • 如果流 ID 为 0,则表示该帧不属于任何流(如 SETTINGS、PING 等帧)。
    • 有效载荷(frame payload):长度帧头中的 Length 字段决定,承载具体的帧内容,不同类型的帧有不同的负载格式。示例如下
      • DATA 帧:包含流的二进制数据。
      • HEADERS 帧:包含经过 HPACK 压缩的 HTTP 首部字段。
      • PING 帧:包含用于测试连接的 8 字节 payload。

image.png

字段 长度 作用
Length 3 字节 表示帧负载的长度(单位:字节)
Type 1 字节 标识帧的类型(如 DATA、HEADERS 等)
Flags 1 字节 标志位,具体含义由帧类型决定
R 1 比特 保留位,必须为 0,否则触发协议错误
Stream Identifier 31 比特 标识帧所属的流 ID,用于多路复用

多路复用

HTTP/2通过多路复用(Multiplexing)彻底解决了队头阻塞问题:

  • 多个请求/响应可以在同一连接上并发传输
  • 每个请求/响应被分配一个唯一的流ID(Stream ID)
  • 帧可以交错发送,接收方根据流ID重新组装

这意味着在单个TCP连接上可以同时处理多个请求,大大提高了连接利用率(类似于连接池)。

image.png

上图就是HTTP/1.X和HTTP/2.0在传输数据时的区别。显然,第二种方式运输数据多,资源的利用率高。

头部压缩

HTTP/1.X的头带有大量信息,而且每次都要重复发送。HTTP/2使用encoder来减少需要传输的header大小,通讯双方各自缓存一份头部字段表,既避免了重复header的传输,又减小了需要传输的大小。

另一方面HTTP/2还引入了HPACK头部压缩算法,相比较HTTP/1.X则不支持压缩。

  • 建立共享的静态和动态字典
  • 重复的头部字段通过字典索引表示
  • 新增的头部字段会被动态添加到字典中
  • 使用Huffman编码进一步压缩头部数据

HPACK压缩显著减少了头部数据的传输量,降低了带宽消耗。

简单介绍压缩原理

  • 用Header字段表里的索引代替实际的header:HTTP/2的HPACK算法使用一份索引表来定义常用的Header,把常用的http Header存放在表里,请求的时候便只需要发送在表里的索引位置即可。

image.png

  • 将字符串进行霍夫曼编码来压缩字符串大小:以常用的 User-Agent 为例,它在静态表中的索引值是 58,它的值是不存在表中的,因为它的值是多变的。第一次请求的时候它的 key 用 58 表示,表示这是一个 User-Agent ,它的值部分会进行霍夫曼编码(如果编码后的字符串变更长了,则不采用霍夫曼编码)。

image.png

服务器推送

HTTP/2允许服务器主动向客户端推送资源:

  • 服务器可以根据客户端的初始请求,预判其可能需要的其他资源
  • 通过发送PUSH_PROMISE帧,服务器可以推送相关资源(如CSS、JS文件)
  • 客户端可以选择接受或拒绝推送的资源

这一特性减少了额外的往返次数,加快了页面加载速度。

  • 注意事项
    • 推送遵循同源策略;
    • 这种服务端的推送是基于客户端的请求响应来确定的。

请求优先级

把HTTP消息分为很多独立帧之后,就可以通过优化这些帧的交错和传输顺序进一步优化性能。每个流都可以带有一个31比特的优先值:0 表示最高优先级;2的31次方-1 表示最低优先级。

服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。高优先级的流都应该优先发送,但又不会绝对的。绝对地准守,可能又会引入首队阻塞的问题:高优先级的请求慢导致阻塞其他资源交付。

  • 优先级最高:主要的html
  • 优先级高:CSS文件
  • 优先级中:js文件
  • 优先级低:图片、视频等其他资源

HTTP/1与HTTP/2的对比

总体结构差异

  • HTTP/1的文本格式:HTTP/1的报文采用纯文本格式,可读性强但效率低
    • 请求和响应由文本行组成
    • 头部字段和值都是明文形式
    • 依赖特定的分隔符(如CRLF)来标识字段结束
  • HTTP/2的二进制格式:HTTP/2采用二进制格式,效率高但不可直接阅读
    • 所有数据以二进制帧形式传输
    • 头部数据经过HPACK压缩
    • 不同类型的数据(头部、正文、控制信息)使用不同的帧类型

头部处理差异

  • HTTP/1的头部处理:HTTP/1的头部处理存在明显缺陷
    • 每个请求都必须重复发送相同的头部字段(如Host、User-Agent)
    • 头部字段以明文形式传输,增加了传输量
    • 头部字段的顺序不固定,可能影响缓存效率
  • HTTP/2的头部处理:HTTP/2通过HPACK算法解决了头部处理的问题:
    • 使用共享字典减少重复传输
    • 头部字段和值被压缩为二进制格式
    • 头部块被拆分为多个帧传输(如果超过一帧的大小)
    • 头部处理更加高效,减少了传输量和处理时间

数据传输差异

  • HTTP/1的数据传输:HTTP/1的数据传输基于文本,采用串行方式
    • 每个请求/响应在单独的连接或流中传输
    • 同一连接上的请求必须按顺序处理
    • 大文件传输可能导致后续请求长时间等待(队头阻塞)
  • HTTP/2的数据传输:HTTP/2的数据传输基于二进制帧,实现了真正的并发
    • 多个请求/响应可以在同一连接上并发传输
    • 数据被拆分为多个帧,通过流ID关联
    • 接收方根据流ID重新组装数据
    • 可以设置流的优先级,优化资源分配

性能对比

连接建立性能对比

HTTP/1和HTTP/2都基于TCP连接,但HTTP/2通常要求TLS加密:

  • HTTP/1.1的纯文本连接只需要TCP三次握手
  • HTTP/1.1的HTTPS连接需要TCP握手+TLS握手(通常需要2-RTT)
  • HTTP/2的HTTPS连接同样需要TCP握手+TLS握手,但可以通过ALPN协商协议版本

吞吐量与延迟对比

image.png

测试表明,HTTP/2在大多数情况下吞吐量高于HTTP/1:

  • HTTP/2的多路复用特性允许在单个连接上并发处理多个请求
  • HTTP/1的持久连接虽然可以重用连接,但同一时间只能处理一个请求
  • 在高并发场景下,HTTP/2的吞吐量优势更加明显

安全性对比

  • HTTP/1本身不要求加密,HTTPS是可选的
    • HTTP/1.1可以在纯文本(HTTP)或加密(HTTPS)模式下运行
    • 许多网站仍然使用纯文本HTTP,存在窃听和篡改风险
    • 即使使用HTTPS,HTTP/1的加密实现也可能存在安全漏洞
  • HTTP/2通常要求加密:
    • 现代浏览器只支持TLS加密下的HTTP/2
    • HTTP/2通过TLS的ALPN扩展协商协议版本
    • 强制加密减少了中间人攻击的风险

特殊场景性能对比

  • 大文件传输:在大文件(如视频、大图片)传输场景中,HTTP/2可能表现不如HTTP/1
    • HTTP/2的多路复用可能导致单个大文件占用过多带宽
    • HTTP/1的持久连接在大文件传输时可能更高效
  • 低带宽网络:在低带宽网络环境下,HTTP/2的优势更加明显
    • HPACK头部压缩减少了不必要的传输量
    • 多路复用减少了连接建立开销
    • 服务器推送减少了额外的往返次数
  • 单页应用(SPA):单页应用通常包含大量的JavaScript和API请求
    • HTTP/2的多路复用减少了多个API请求的延迟
    • 头部压缩减少了重复的头部传输
    • 服务器推送可以预加载关键资源
  • 移动应用:移动应用通常面临网络不稳定和带宽受限的问题:
    • HTTP/2的头部压缩减少了数据传输量
    • 多路复用减少了连接建立次数
    • 在高延迟网络环境下表现更好

综合对比

特性 HTTP/1 HTTP/2
协议格式 文本格式 二进制分帧
连接管理 持久连接(默认) 多路复用
头部处理 明文传输,重复发送 HPACK压缩,共享字典
并发处理 管道化(有限支持) 真正的并发
服务器推送 不支持 支持
安全性 可选加密(HTTPS) 通常要求加密(TLS)
性能 较低,存在队头阻塞 较高,解决了队头阻塞