HTTP 是基于 TCP/IP 协议的一个应用层协议,是现代互联网的一个基础协议。规定了客户端与服务端之间的通信格式以及所占用的服务端口80(HTTPS是443)。
版本
HTTP 协议从开始立项到现在一共经历了 5 个版本:
HTTP 0.9 -> HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0
HTTP 0.9
- 只支持GET请求方式:由于不支持其他请求方式,因此客户端是没办法向服务端传输太多的信息
- 没有请求头概念:所以不能在请求中指定版本号,服务端也只具有返回 HTML字符串的能力
- 服务端相响应之后,立即关闭TCP连接
HTTP 1.0
- 请求方式新增了POST,DELETE,PUT,HEADER等方式
- 增添了请求头和响应头的概念,在通信中指定了 HTTP 协议版本号,以及其他的一些元信息 (比如: 状态码、权限、缓存、内容编码)
- 扩充了传输内容格式,图片、音视频资源、二进制等都可以进行传输
在这个版本主要就是对请求和响应的元信息进行了扩展,客户端和服务端有更多的获取当前请求的所有信息,进而更好更快的处理请求相关内容。
请求头
一个简单请求的头信息,可以看到在请求方法之后有 请求资源的位置 + 请求协议版本,之后是一些客户端的信息配置:
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
响应头
一个简单响应的头信息(v1.0),服务端的响应头第一个就是 请求协议版本,后面紧跟着是这次请求的状态码、以及状态码的描述,之后的内容是一些关于返回内容的描述:
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
// 这是一个空行
...数据内容
Content-Type
在 HTTP 1.0 的时候,任何资源都可以被传输,传输的格式也是多种多样的,客户端在收到响应体的内容的时候就是根据这个 Content-Type 去进行解析的,所以服务端返回时候必须带着这个字段。这些 Content-Type 有一个总称叫做MIME type。关于MIME type,这里想播插一个小插曲:
在 chrome 浏览器中,当跨域请求回来的数据 MIME type 同跨域标签应有的 MIME type 不匹配时,浏览器会启动 CORB 保护数据不被泄漏。被保护的数据有: html、xml、json(eg: script、img 标签所支持的 MIME type和他们都不一致),所以服务端在返回资源的时候一定要对应返回正确的 Content-Type,以免浏览器屏蔽返回结果。
特性
- 无状态:服务器不跟踪不记录请求过的状态
- 无连接:浏览器每次请求都需要建立tcp连接
无状态
对于无状态的特性可以借助cookie/session机制来做身份认证和状态记录
无连接
无连接导致的性能缺陷有两种:
- 无法复用连接:每次发送请求,都需要进行一次tcp连接(即3次握手4次挥手),使得网络的利用率非常低
- 队头阻塞:HTTP 1.0 规定在前一个请求响应到达之后下一个请求才能发送,如果前一个阻塞,后面的请求也给阻塞的
HTTP 1.1
HTTP 1.1 是在 1.0 发布之后的半年就推出了,完善了 1.0 版本。目前也还有很多的互联网项目基于 HTTP 1.1 在向外提供服务。
- 长连接:新增Connection字段,可以设置keep-alive值保持连接不断开
- 管道化:基于上面长连接的基础,管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回
- 缓存处理:新增字段cache-control
- 断点传输
长连接
HTTP 1.1默认保持长连接,数据传输完成保持tcp连接不断开,继续用这个通道传输数据
管道化
基于长连接的基础,我们先看没有管道化请求响应:
tcp没有断开,用的同一个通道:
请求1 > 响应1 --> 请求2 > 响应2 --> 请求3 > 响应3
管道化的请求响应:
请求1 --> 请求2 --> 请求3 > 响应1 --> 响应2 --> 响应3
即使服务器先准备好响应2,也是按照请求顺序先返回响应1,虽然管道化,可以一次发送多个请求,但是响应仍是顺序返回,仍然无法解决队头阻塞的问题。
缓存处理
当浏览器请求资源时,先看是否有缓存的资源,如果有缓存,直接取,不会再发请求,如果没有缓存,则发送请求, 通过设置字段cache-control来控制缓存。
断点传输
在上传/下载资源时,如果资源过大,将其分割为多个部分,分别上传/下载,如果遇到网络故障,可以从已经上传/下载好的地方继续请求,不用从头开始,提高效率。
HTTP 2
- 二进制分帧
- 多路复用: 在共享TCP链接的基础上同时发送请求和响应
- 头部压缩
- 服务器推送:服务器可以额外的向客户端推送资源,而无需客户端明确的请求
二进制分帧
HTTP 1.x 的解析是基于文本,HTTP 2 之后将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码,提高传输效率
多路复用
在共享TCP连接的基础上同时发送请求和响应,基于二进制分帧,在同一域名下所有访问都是从同一个tcp连接中走,http消息被分解为独立的帧,乱序发送,服务端根据标识符和首部将消息重新组装起来。
头部压缩
由于 HTTP 是无状态的,每一个请求都需要头部信息标识这次请求相关信息,所以会造成传输很多重复的信息,当请求数量增大的时候,消耗的资源就会慢慢积累上去。所以 HTTP 2 可以维护一个头部信息字典,差量进行更新头信息,减少头部信息传输占用的资源。
存在的缺点
- 建立连接时间长
- 队头阻塞问题相较于 HTTP/1.1 更严重
HTTP 3.0
HTTP/3 采用了谷歌多年探索的基于 UDP 的 QUIC 协议,原名叫 HTTP-over-QUIC,在 2018 年被 IETF 批准更名为 HTTP/3。目前,Cloudflare、Google Chrome、Firefox Nightly 均表示支持 HTTP/3。
QUIC 是一种通用传输协议,与 TCP 非常相似,除了 HTTP 和网页加载之外,它还可以并且将用于更多场景,例如 DNS、SSH、SMB、RTP 等都可以在 QUIC 上运行。
- 使用 UDP 协议,不需要三次握手进行连接,缩短了 TLS 建立连接的时间
- 多路复用,解决队头阻塞问题
- ORTT:通过使用类似 TCP 快速打开的技术,缓存当前会话的上下文,在下次恢复会话的时候,只需要将之前的缓存传递给服务端验证通过就可以进行传输了
- 向前纠错机制:每个数据包除了它本身的内容之外,还包括了部分其他数据包的数据,因此少量的丢包可以通过其他包的冗余数据直接组装而无需重传
- 加密认证的报文:报文头和报文体分别进行认证和加密处理,保障安全性
HTTPS 和 HTTP 区别
- HTTPS 协议需要申请证书
- HTTP 和 HTTPS 使用端口不一样,前者是80,后者是443
- HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,HTTPS 运行在 SSL/TLS 之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的