HTTP 0.9
日期:1991
- 只支持GET请求方式
- 服务器只返回html字符串信息,不包含头信息
- 服务器返回后就断开tcp连接
- 只有一个请求行,并没有HTTP 请求头和请求体
- 是返回的文件内容是以 ASCII 字符流来传输的 世界上第一个网站info.cern.ch
HTTP 1.0
日期:1996
- 引入了请求头和响应头
- 支持GET,POST,HEAD请求方式
- 新增了请求的字段 文件类型,压缩,编码格式,使用语言(多字符集)
accept: text/html
accept-encoding: gzip, deflate, br
accept-Charset: ISO-8859-1,utf-8
accept-language: zh-CN,zh
- 新增了服务端响应字段
content-encoding: br
content-type: text/html; charset=UTF-8
- 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
- 多部分对象集合(Multipart) 如文件上传 Content-Type: multipart/form-data ,HTTP 协议中使用了多部分对象集合,发送的一份报文主体内可含有多类型实体
- 缓存Expires
- 新增状态码
- 可以使用Connection:keep-alive 实现请求后,tcp不断开,但是不是标准,并不是每个浏览器都支持。
- 新增http header信息来描述元数据。
- 增加了用户代理UserAgent获取客户端的基础信息
- 权限
缺陷:
- 无状态: 服务器不跟踪不记录请求过的状态: 可以借助 cookie/session 机制做身份认证和状态记录
- 无连接:无法复用连接, 每次都需要进行三次握手, 四次挥手, 浪费网络资源
- 队头阻塞: HTTP1.0 规定, 在前一个响应完成后, 下一次请求才能发出, 如果前一个阻塞, 后面的请求也阻塞了
HTTP 1.1
日期:1999 当前-主流
- 在原有的基础上新增了许多请求方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。
- 官方默认就支持Persistent Connection(持久连接), Connection: keep-alive,不用特意声明。 客户端和服务器发现对方一段时间没有活动,服务端会有keepAliveTimeout超时时间(nginx 60秒),主动发起关闭连接。或者连接数maxKeepAliveRequests 超过指定请求,也会主动发起关闭连接。 当然客户端也可以主动发送 Connection: close,明确要求服务器关闭 TCP 连接。
- 尚未成熟的HTTP 管线化 :传统tcp一次只能发送一个请求A,等请求A结束后才能重新发起请求B。但是在管道机制中,一个tcp可以发起多个请求,不过服务端还是会按顺序返回A和B的内容。由于同时进行,就需要区分数据包。使用Content-length区分,由于服务端还是按顺序响应,所以效果不明显。
- 客户端请求的头信息新增了 Host 字段,用来指定服务器的域名。由于在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址,就需要通过Host区分
- 支持文件断点续传,RANGE:bytes,用于分片下载
- 支持只发送header信息,并且加入了一个新的状态码100。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。
- 新的缓存策略Cache-Control
- 对动态内容的支持Transfer-Encoding
- 客户端 Cookie和安全机制
Transfer-Encoding
由于 Content-Length 字段必须真实反映实体长度,但实际应用中,有些时候实体长度并没那么好获得,例如实体来自于网络文件,或者由动态语言生成。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。
- 当 Content-Length 大于实际值会超时
- 当 Content-Length小于实际值会截断并可能导致后续的数据解析混乱。
Transfer-Encoding: chunked 该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据), Content-Length将被忽略。
HTTP 2.0
日期:2015 Google SPDY方案
针对http1.1的痛点做优化
- 慢启动,为了避免启动暂用太多资源,策略是先慢后快
- 多个tcp会互相竞争资源,当网速不足时,部分tcp会进行降速处理
- http队头阻塞,管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。
解决方案-多路复用
- 多路复用,一个域名只保留一个tcp,只有一次慢启动,也不存在资源竞争
- 对头阻塞是通过把所有数据分帧传输,服务端选择性返回
- 基于二进制数据帧的传输、消息、流,所以可以做到乱序的传输,所有请求都是基于流。
- 支持请求设置优先级
- 服务器推送
- 头部压缩
- 增加全双工模式,不仅客户端能够同时发送请求,服务端也能同时处理多个请求,解决了队头堵塞的问题.
- 添加数据编号,可以取消某一次请求
- 彻底的二进制协议,头信息和数据体都是二进制,将所有的信息字段建立一张表,头信息复用,通过不同帧不不同处理
多路复用原理
- 在http 和 tcp中间 加入了 二进制分帧层
- http层数据会被转化为一个个带有请求ID编号的帧,通过协议栈将这些帧发送给服务器
- 服务器接收到所有帧之后,会将所有相同ID的帧合并为一条完整的请求信息。
- 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
- 二进制分帧层会将这些响应数据转换为一个个带有请求ID编号的帧,经过协议栈发送给浏览器。
- 浏览器接收到响应帧之后,会根据ID编号将帧的数据提交给对应的请求。
HTTP 3.0
日期:2018
tcp的缺陷
-
依然没有解决tcp层面包的队头阻塞问题,而且http2一个域名只有一个tcp,当丢包严重更容易导致全停顿
-
tcp 连接耗时,3次握手需要1.5个RTT,ssl 握手1-2RTT,共需要3-4个RTT
Round Trip Time 浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为 RTT
-
TCP 协议僵化,升级tcp版本很难
- 中间设备的僵化,早期很多硬件和软件都对tcp做了定制或优化
- 操作系统只对tcp做了优化比较多
解决方案-使用QUIC
- 实现了类似 TCP 的流量控制、传输可靠性的功能。虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
- 集成了 TLS1.3 加密功能。
- 实现了 HTTP/2 中的多路复用功能。在同一物理连接上可以有多个独立的逻辑数据流。实现了数据流的单独传输
- 实现了快速握手功能。0-RTT 或者 1-RTT 来建立连接
- 流量控制
- 快速重启会话:普通基于tcp的连接,是基于两端的ip和端口和协议来建立的。在网络切换场景,例如手机端切换了无线网,使用4G网络,会改变本身的ip,这就导致tcp连接必须重新创建。而QUIC协议使用特有的UUID来标记每一次连接,在网络环境发生变化的时候,只要UUID不变,就能不需要握手,继续传输数据。
http3面临的困难
- 服务端和客户端对http3的支持不够
- 各个操作系统对UDP的优化没有TCP那么完善和成熟
- 中间设备不怎么支持UDP,导致丢包率高
HTTPS
日期1994 ,网景在1994年创建了HTTPS
基于http的基础上,新增ssl加密。
- 确认服务端的身份
- 主要实现传输通道的加密,保证客户端到服务端过程中,不被篡改或窃听。
而实际的内容传输依然保留原来的http的传输内容,也就是不加密。