当前位置: 首页 > news >正文

HTTP协议版本的发展(HTTP/0.9、1.0、1.1、2、3)

目录

HTTP协议层次图

HTTP/0.9

例子

HTTP/1.0

Content-Type 字段

Content-Encoding 字段

例子

1.0版本存在的问题:短链接、队头阻塞

HTTP/1.1

Host字段

Content-Length 字段

分块传输编码

1.1版本存在的问题

HTTP/2

HTTP/2数据传输

2版本存在的问题

HTTP/3

队头阻塞问题总结

HTTP1.1断点续传

如果服务器支持断点续传

如果服务器不支持断点续传

断点续传的应用

HTTP Keep-Alive 机制


HTTP协议层次图

HTTP/0.9

HTTP/0.9是最早的一个版本,在1991年发布,只有GET一种请求方法,并且不支持请求头。只支持纯文本一种内容,服务器只能响应HTML格式的字符串,且不能插入图片。HTTP/0.9具有典型的无状态、无连接特性。

例子

请求:
GET /index.html

响应:

<html><body>Hello World</body>
</html>

HTTP/1.0

HTTP/1.0协议于1996年发布,是一种无状态、无连接的应用层协议。
  • 增加POST、HEAD等请求方法。
  • 引入头部信息。除了要传输的数据之外,每次通信都包含头信息,用来描述一些信息。
  • 传输数据格式不再局限于HTML格式。根据Content-Type可以支持多种数据格式,不仅可以用来传输文字,还可以传输图像、音频、视频等二进制文件。
  • 引入cache缓存机制。
  • 引入状态码。

Content-Type 字段

关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。

下面是一些常见的Content-Type字段的值。

text/plain

text/html

text/css

image/jpeg

image/png

image/svg+xml

audio/mp4

video/mp4

application/javascript

application/pdf

application/zip

application/atom+xml

Content-Encoding 字段

由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。

Content-Encoding: gzip

Content-Encoding: compress

Content-Encoding: deflate

客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法:

Accept-Encoding: gzip, deflate

例子

请求:

GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。Accept: */*:表明户端可以接受任何格式的数据。

响应:

HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html><body>Hello World</body>
</html>

1.0版本存在的问题:短链接、队头阻塞

  • 短链接:每个TCP连接只能发送一个请求,当服务器响应后就会关闭这个TCP连接,下一次请求需要再次建立TCP连接。每次建立、释放TCP连接需要三次握手四次挥手,所以当网页需要发送多个HTTP请求时,就会造成性能问题。
  • 队头阻塞:下一个请求必须在前一个请求响应到达之前才能发送,若前一个请求响应一直不到达,那下一个请求就不发送,同样后面的请求也被阻塞了。

HTTP/1.1

为解决HTTP/1.0短连接造成的性能开销,HTTP/1.1引入了持久连接。
  • 新增了请求方式PUT、PATCH、OPTIONS、DELETE等。
  • 增强缓存策略:如Etag、If-Unmodified-Since、If-Match、If-None-Match等可供选择的了缓存头来控制缓存策略。
  • 客户端请求的头信息新增了Host字段,用来指定服务器的域名。
  • 引入持久连接(即长连接) :可以通过设置connection: keep-alive来保持HTTP连接不断开,避免频繁的建立、释放连接。如果客户端和服务器端发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求是,发送connection: false来明确要求服务器关闭TCP连接。(1.1默认有长链接,1.0需要手动的添加connection: keep-alive才能保持长链接
  • 加入管道机制:基于HTTP/1.1的长链接,在同一个TCP连接里,允许多个请求同时发送。但是还是有问题:假设客户端需要请求两个资源。以前的做法是,在同一个TCP连接里,先发送A请求,然后等待服务做出响应,收到后再发出B请求。管道机制允许浏览器同时发出A请求和B请求,但服务器还是按照请求顺序,先响应A请求,再响应B请求,所以这并不是真正意义上的并行传输。现阶段的浏览器厂商实现并行传输,采用的做法是允许打开多个TCP会话,这就是我们所熟悉的浏览器对同一个域下能够并行加载6~8个资源的限制。(所以说HTTP/1.1 管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞)
  • HTTP/1.1支持文件断点续传:RANGE:bytes,HTTP/1.0每次传送文件都是从文件头开始,即0字节处开始。RANGE:bytes=XXXX表示要求服务器从文件XXXX字节处开始传送,断点续传。返回码是206(Partial Content)
  • Content-length字段:声明本次回应的数据长度。
  • 分块传输编码:使用Content-Length字段的前提条件是服务器发送响应之前,必须知道响应的数据长度。对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用“流模式”(stream),取代“缓存模式”(buffer)。因此,1.1版本规定可以不使用Content-Length字段,而使用“分块传输编码”,只要请求或回应的头信息有Transfer-Encoding字段,就表明响应将由数量未定的数据块组成。

Host字段

Host 请求头字段的引入主要是为了解决虚拟主机(Virtual Hosting)的问题,即 一台物理服务器托管多个域名网站时,如何正确区分不同域名的请求。
  • HTTP/1.0 的问题:在 HTTP/1.0 中,请求只包含路径(如 GET /index.html),不包含域名信息。如果一台服务器托管了 example.com 和 test.com,服务器无法区分请求是发给哪个域名的。
  • HTTP/1.1 的解决方案:强制要求客户端在请求头中添加 Host 字段,明确指定目标域名:服务器会根据 Host 字段将请求路由到对应的网站。如下:
GET /index.html HTTP/1.1
Host: example.com

Content-Length 字段

一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。

Content-Length: 3495

上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。

在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了

分块传输编码

Transfer-Encoding: chunked // 分块传输

每一个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完毕:

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked25
This is the data in the first chunk1C
and this is the second one3
con8
sequence0

1.1版本存在的问题

1.1使用持久连接、管道化优化了性能,但没有彻底解决队头阻塞问题。

HTTP/2

  • 二进制分帧:HTTP/1.1版本的头信息必须是文本(ASCII编码),数据体可以是文本,也可以是二进制,HTTP/2则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为“帧”(frame):头信息帧和数据帧。如下图:
  • 多路复用:HTTP/2版本会复用TCP连接。在一个连接里,客户端和服务器端都可以同时发送多个请求或响应,而且不用按照顺序一一对应,这样就避免了“队头阻塞”。(多路复用是通过 流Streams和 二进制帧Frames实现的,而非直接复用原始 HTTP 消息)
  • 数据流:因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。
客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
  • 头信息压缩:HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
  • 服务器推送:HTTP/2允许服务器不需要客户端的请求就可以主动向客户端发送资源。
常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。
  • 流量控制: HTTP/2不同于HTTP/1.1的只要客户端可以处理,服务端就会尽可能快地发送数据。HTTP/2提供了客户端调整传输速度的能力(服务端也可以),在每一个数据帧中告诉对方,发送方想要接受多少字节的数据。

HTTP/2数据传输

从图中可见,所有的HTTP/2通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流。

每个数据流以消息的形式发送,而消息由一个或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的stream id标识符来重新组装。

举个例子,每个请求是一个数据流,数据流以消息的方式发送,而消息又分为多个帧,帧头部记录着stream id用来标识当前帧所属的数据流,不同属的帧可以在连接中混杂在一起。接收方可以根据stream id将帧再归属到各自不同的请求中去。

另外,多路复用(连接共享)可能会导致关键请求被阻塞。HTTP/2里每个数据流都可以设置优先级和依赖,优先级高的数据流会被服务器优先处理和返回给客户端,数据流还可以依赖其他的子数据流。

2版本存在的问题

队头阻塞:

HTTP/2 的多路复用依赖于一条 TCP 连接,而 TCP 是面向字节流的协议,要求数据按顺序到达,如果某个TCP 包丢失,那么整个连接会等待重传,导致所有流被阻塞。

HTTP/3

HTTP/3 基于 QUIC 协议(Quick UDP Internet Connections),解决了 HTTP/2 的遗留问题。
  • TCP 队头阻塞:HTTP/2 的 多路复用 在 TCP 上运行时,若一个包丢失,所有流(Stream)都会被阻塞。HTTP/3 使用 QUIC(基于 UDP),每个流独立传输,丢包只影响当前流,其他流不受影响。

HTTP/3 只使用一个 UDP 连接,但在这个连接内部通过 QUIC 协议 实现了多路复用,而不是建立多个 UDP 连接。在单个 UDP 连接内创建多个Streams流,每个 HTTP 请求/响应对应一个独立的 QUIC 流(使用Stream ID标识),这些流共享同一个 UDP 连接,但彼此独立,所以一个流丢包不会阻塞其他流传输消息。

  • 减少握手延迟HTTP/2 需要 TCP 三次握手 + TLS 握手(1~2 RTT),而 HTTP/3 的 QUIC 直接内置 TLS 1.3,支持:
    • 1-RTT 首次连接(比 HTTP/2 更快)。
    • 0-RTT 恢复连接(对之前访问过的服务器可立即发送数据)。

队头阻塞问题总结

HTTP1.0存在短链接、队头阻塞问题
HTTP/1.1 通过以下改进减少了部分性能问题,但未彻底解决队头阻塞:
  • 持久连接(Keep-Alive):默认复用同一个 TCP 连接,避免了频繁建立连接的开销。
  • 管道化(Pipelining):允许客户端在未收到响应时发送多个请求(理论上的优化)。(响应必须按请求顺序返回:如果第一个请求的响应延迟(例如服务器处理慢或网络延迟),后续已发送的请求响应会被阻塞,即使它们已经准备就绪。)
HTTP/2 和 HTTP/3:
  • HTTP/2:通过多路复用(Multiplexing)在单个连接上并行传输多个请求/响应,彻底解决了应用层的队头阻塞。但若底层 TCP 丢包,仍会因重传导致所有流阻塞(TCP 层队头阻塞)。
  • HTTP/3:基于 QUIC 协议(UDP 实现),解决了 TCP 层的队头阻塞,每个流独立传输,丢包不影响其他流。

HTTP1.1断点续传

HTTP/1.1 通过 Range 请求头 和 Content-Range 响应头 支持文件的断点续传(Partial Content),允许客户端只请求资源的某一部分,而不是整个文件。这在下载大文件、视频流或恢复中断的下载时非常有用,可以 有效避免重复下载

如果服务器支持断点续传

客户端发起带 Range 头的请求:客户端在请求中指定需要下载的字节范围(如从第 1000 字节开始)。

GET /large-file.zip HTTP/1.1
Host: example.com
Range: bytes=1000-2000
  • Range: bytes=start-end:请求文件的特定字节范围(end 可省略,表示直到文件末尾)。
  • 例如:
    • Range: bytes=0-499 → 请求前 500 字节
    • Range: bytes=500- → 请求从第 500 字节到文件末尾
    • Range: bytes=500-999,2000-2499 → 请求多个范围(较少使用)

如果服务器支持断点续传,会返回 206 状态码,并标明返回的数据范围:

HTTP/1.1 206 Partial Content
Content-Range: bytes 1000-2000/5000
Content-Length: 1001
Content-Type: application/zip[文件数据...]
  • Content-Range: bytes start-end/total:
    • start-end:实际返回的字节范围
    • total:文件的完整大小(如果未知,可以用 * 代替)
  • Content-Length:返回的数据长度(这里是 2000 - 1000 + 1 = 1001 字节)

客户端继续下载剩余部分:客户端可以继续发送新的 Range 请求,直到文件下载完成。

注意:如果客户端请求的字节范围不合法,比如超出了请求文件的大小,那么服务端就会返回416状态码。
StatusRequestedRangeNotSatisfiable(请求的状态范围不满足) = 416

如果服务器不支持断点续传

如果服务器不支持 Range 请求,会直接返回 200 OK 和整个文件:

HTTP/1.1 200 OK
Content-Length: 5000
Content-Type: application/zip[完整的文件数据...]

客户端需要检查状态码是 206 还是 200 来判断是否支持断点续传。

StatusPartialContent(状态部分内容)= 206

断点续传的应用

  1. 大文件下载(如 ISO 镜像、视频文件):下载工具(如迅雷、IDM)可以分块下载,提高速度。如果下载中断,可以从中断的位置继续下载,而不是重新开始。
  2. 视频/音频流(HTTP Streaming):播放器可以只请求视频的某一段(如 Range: bytes=0-1023),实现边下边播。
  3. 断网恢复:浏览器或下载管理器可以记录已下载的字节位置,恢复时发送 Range 请求继续下载。

HTTP Keep-Alive 机制

HTTP Keep-Alive(也称为持久连接,Persistent Connection)是一种允许在单个TCP连接上发送和接收多个HTTP请求/响应的机制。它通过复用TCP连接,减少因频繁建立/关闭连接带来的性能开销。
工作原理:
  • 传统HTTP(无Keep-Alive):每个HTTP请求完成后立即关闭TCP连接,下次请求需重新建立连接(三次握手)。
请求1 → 响应1 → 关闭连接
请求2 → 响应2 → 关闭连接
  • 启用Keep-Alive后:多个HTTP请求复用同一个TCP连接,减少握手和挥手次数。
请求1 → 响应1 → 请求2 → 响应2 → ... → 关闭连接
实现方式:
  • HTTP/1.1:默认启用Keep-Alive(无需显式声明),除非请求头包含 Connection: close。
  • HTTP/1.0:需显式在请求头中添加 Connection: keep-alive。
示例请求头:
GET /index.html HTTP/1.1
Host: example.com
Connection: keep-alive  # 显式启用(HTTP/1.0需此字段,HTTP/1.1可省略)

参考:

HTTP 协议的历史演变和设计思路 

稀土掘金:HTTP协议各个版本之间的区别

相关文章:

  • 黑马点评-分布式锁Lua脚本
  • 进阶-自定义类型(结构体、位段、枚举、联合)
  • Lua基础语法
  • 在Windows平台基于VSCode准备GO的编译环境
  • Mustache 模板引擎详解_轻量、跨语言、逻辑无关的设计哲学
  • 一文讲透golang channel 的特点、原理及使用场景
  • 正则表达式:字符串模式匹配的利器
  • 历年华南理工大学保研上机真题
  • 什么是前端工程化?它有什么意义
  • 并发编程(6)
  • linux学习第15天(dup和dup2)
  • GO 语言进阶之 进程 OS与 编码,数据格式转换
  • Docker(零):本文为 “Docker系列” 有关博文的简介和目录
  • 二叉树--oj1
  • 计算机基础核心课程
  • 详解Mysql redo log与binlog的两阶段提交(2PC)
  • 2025年AI代理演进全景:从技术成熟度曲线到产业重构
  • 加密货币投资亏损后,能否以“欺诈”或“不当销售”索赔?
  • 【JAVA】线程创建方式:继承Thread vs 实现Runnable(32)
  • LeetCode-图论-岛屿数量+腐烂的橘子
  • 网站开发预算报表/百度官方网
  • 上海opencart网站建设/网站推广的具体方案
  • 浩森宇特北京网站建设/在线代理浏览网址
  • 小程序制作需要什么技术/长沙排名优化公司
  • 做网站开发学什么语言/国际站seo优化是什么意思
  • dw做网站一般设为什么样/百度热搜榜怎么打开