http 0.9
特点:
- 只有有个请求行,没有 http 请求头和请求体
- 服务器也没有返回头信息
- 返回的文件都是 html 格式的文件,所以是使用 ASCII 字符流传输的
http 1.0
出现原因:浏览器中展示的不只是 html 文件,还有 js,css,图片,音频等不同类型的文件,所以需要支持多种类型的文件下载
解决方法:引入了请求头和响应头,以 key-value 的形式保存
如何通过请求头和响应头来支持多种不同类型的数据?
- 浏览器需要知道服务器返回的数据是什么类型的
- 单个文件的数据量越来越大,为了加快传输的速度,服务器会对数据进行压缩后再传输,所以浏览器需要知道服务器压缩的方法
- 不同地区的语言可能不同,所以浏览器需要告诉服务器它需要什么语言版本的界面
- 不同文件的编码形式可能不一样,所以浏览器需要知道文件的编码类型
除了对多文件的支持外,还根据当时的需求加入了其他的新特性:
- 一些请求服务器可能处理不了或者处理出错,所以引入了状态码来通知浏览器请求的结果如何
- 为了减轻服务器的压力,提了 Cache 机制,用来缓存已经下载过的数据
- 服务器需要统计客户端的基础信息,例如当前客户端是 Windows 还是 macOS 的,所以在请求头中加入了 用户代理 字段
http 1.1
出现原因:随着技术的发展,http 1.0 也逐渐不能满足需求了,所以 http 1.1 在 http 1.0 的基础上又制作了大量的更新
- 增加了持久连接 http 1.0 每次通信都需要经历 tcp 连接,传输 http 数据和断开 tcp 连接三个阶段。单个页面中的文件比较少的时候还好,如果文件多了例如有几百个文件,那么就浪费了很多时间在 tcp 连接和 tcp 断开上面。
为了解决这个问题,http 1.1 中增加了持久连接的方法,只要浏览器或者服务器没有明确断开连接,那么该 tcp 连接就会一直保持着,这样一个 tcp 连接上面就可以传输多个 http 请求。
这个特性是默认开启的,要关闭的话可以在 http 请求头中加入 connection: close。
对于同一个域名,默认允许同时建立六个 tcp 持久连接。
- http 管线化解决队头阻塞问题
持久连接能减少 tcp 的建立和断开次数,但是需要等待上一个请求返回之后才能进行下一个请求,如果某个请求没有及时返回,那么后面所有的请求就会被阻塞,这就是队头阻塞问题
http 1.1 试图通过将多个 http 请求整批提交给服务器来解决这个问题,虽然可以整批发送请求,但是服务器那边依然需要根据请求的顺序来回复浏览器的请求,整批发送请求就是管线化
- 支持虚拟主机
在 http 1.0 中,每个域名绑定了一个唯一的 ip 地址,因此一个服务器只能支持一个域名。后面随着技术的发展,一台物理主机上可以绑定多个虚拟主机,每个虚拟主机有自己独立的域名,这些域名共用一个 ip 地址
所以 http 1.1 的请求头中增加了 host 字段,用来表示当前的域名地址,让服务器那边能根据不同的 host 进行不同的处理
- 支持动态生成的内容
引入了 chunk transfer 机制解决浏览器不知道服务端传输数据大小的问题,服务端将数据分割成若干个任意大小的数据块,每个数据块在发送的时候附上上一个数据块的长度,最后使用一个长度为零的块作为数据发送完成的标志,通过这个机制来支持动态内容
- 客户端 cookie 和安全机制
为了解决 http 无状态的问题,http 1.1 引入了 cookie,cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向统一服务器再发起请求时被携带并发送到服务器上。主要用途有三个:会话状态管理,个性化设置和浏览器行为追踪
使用 cookie 有可能导致 XSS (跨站脚本攻击) 和 CSRF (跨站请求伪造)问题,可以使用 HttpOnly 来防止通过 js 访问 cookie,用于敏感信息的 cookie 可以将生存期缩短,同时还要对用户的输入进行过滤
http 2.0
http 1.1 的问题:对带宽的利用率不理想,很难将带宽用满
出现原因:
- tcp 的慢启动
- 同时开启了多条 tcp 连接,这些连接会竞争固定的带宽
- http 1.1 队头阻塞问题
解决方法:多路复用
一个域名只使用一个 tcp 长连接,同时实现了资源的并行请求
每个请求都有对应的 ID,这样浏览器就可以随时将请求发送给服务端。服务端收到请求后根据优先级来决定返回的内容,比如收到某些比较重要的 js 资源的请求时,可以暂停当前的请求来处理这个 js 的请求。因为每份数据都有对应的 ID,所以浏览器收到数据后可以筛选出相同 ID 的内容,将其拼接为完整的 http 响应数据
多路复用技术是通过在协议中加了一个 二进制分帧层 来实现的,通过 二进制分帧层 进行请求和响应的过程如下:
- 浏览器准备好请求的数据,包括请求行,请求头等
- 请求的数据经过二进制分帧层的处理之后,会被转化为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器
- 服务器接收到所有的帧之后,将所有 ID 相同的帧合成一条信息完整的请求
- 服务器处理该请求,并将处理后的响应行,响应头和响应体分别发送至二进制分帧层
- 二进制分帧层将这些数据转换为一个个带有请求 ID 编号的帧,通过协议栈发送给浏览器
- 浏览器接收到响应帧之后,根据 ID 编号将帧的数据提交给对应的请求
http 2 的其他特性:
- 可以设置请求的优先级
- 服务器推送
- 头部压缩