这篇笔记来梳理一下http各个版本的不同特性。
HTTP/0.9
最早诞生的是HTTP/0.9,是1991年提出的,当时是用来在网络间传递HTML超文本的内容,主要用于学术交流。
- 客户端与服务器建立TCP连接,(连接过程即TCP协议三次握手的过程)
- 发送GET请求行的信息。(当时的请求是只有一个请求行,没有HTTP请求头和请求体,因为只需要一个请求行就可以完整表达客户端的需求了)
- 服务端读取对应的HTML文件,将数据以ASCII字符流返回给客户端。(服务器也没有返回头信息)
- HTML文档传输完成后,断开连接。
HTTP/1.0
后来万维网进入高速发展阶段,在浏览器里面不仅仅展示HTML文件,还包括JS、CSS、图片、音频、视频等不同类型的文件,文件格式不再局限于ASCII编码,而且单个文件的数据量变大了,并且万维网支持全球范围所以需要进行国际化。所以HTTP/1.0诞生了。
HTTP/1.0引入了请求头
和响应头
,客户端在发送请求时会带上请求头信息,服务器在返回数据时也会返回响应头信息。
HTTP/1.0在头信息里面,客户端和服务器进行协商,可以知道服务器返回的数据是什么类型的、文件是否被压缩及压缩的形式、文件的语言版本、文件的具体编码等。
HTTP/1.0除了通过请求头和响应头来支持了多种类型的文件,还引入了状态码
,可以知道服务器的处理情况。并且提供了Cache机制
,用来缓存已经下载过的数据,以减轻服务器的压力。并且还加入了User-Agent
字段来区分客户端的一些信息。
HTTP/1.1
HTTP/1.0每次进行通信,都要建立连接、传输数据、断开连接。当单个网页的内容越来越多的时候,每个网页里面有很多文件,如果都需要经历这三年各步骤,那么就相当于增加了很多耗时。
所以在HTTP/1.1里面增加了长连接
,即多个请求可以复用同一个持久连接,即Connection: keep-alive
,默认是开启的。
注意:浏览器里面的限制是,对于同一个域名,默认允许同时建立6个TCP持久连接。(也因为这个限制,所以现在大部分的前端方案是,将不同类型的资源放在不同的域名下面)
使用长连接,虽然可以减少建立连接的开销,但是会有队头阻塞
问题。即前面的请求返回之后,才能进行下一次请求。
以前文件很小的时候,很容易知道文件的具体大小,在响应头的Content-Length
里面告诉客户端。后来因为文件太大而有了文件压缩机制。当然对于大文件,还可以分块进行传输,所以引入了Chunk transfer机制
,将数据分割成若干个数据块,每个数据块会有上个数据块的长度信息,最后使用一个零长度的块作为发送数据完成的标志,分块传输Transfer-Encoding: chunked
和Content-Length
是不能同时出现的。
HTTP/1.1还引入了Cookie机制,响应头里面有Set-Cookie
字段表示是服务器给客户端的身份标识,请求头收到响应报文之后,就把这个字段里面的值存起来,下次再请求的时候就把这个值放到Cookie
字段里面发给服务器。服务器发现收到的请求里面有Cookie
字段,就可以识别用户的身份。
HTTP/1.1还有安全机制,例如Cookie的HttpOnly属性让js脚本不能通过document.cookie读取Cookie,那么即使有恶意js脚本,我们的cookie也是安全的。
HTTP/2
由于HTTP/1.1的队头阻塞问题,HTTP/2提出了多路复用
机制:
- 一个域名只使用一个TCP长连接来传输数据。这样的话可以避免多个TCP长连接的多个慢启动问题,只需有一次慢启动就行。
- 通过
二进制分帧层
来将请求数据分成一帧一帧的数据。所以不需要等待前面的请求处理完成才能进行下一个请求。
一帧一帧的数据都是二进制的,不再像以前那样是ASCII编码的纯文本。
由于不同的请求都会被拆成一帧一帧的数据,所以同一个消息往返的帧会分配一个唯一的流ID,这样在就可以正确的识别同一个请求的数据。
HTTP/2还对头部进行了压缩。以前HTTP的头的信息度其实不高,由于是明文字符串表示头信息,而且每个请求里面都会有User-Agent
、Host
、Accetp
等这种固定字段,其实是很大的资源浪费。所以在HTTP/2里面进行了头部压缩
,采用具体的索引号来表示重复的字符串,并且使用哈弗曼编码来压缩整数和字符串,大概可以达到50%~90%的压缩率
HTTP/3
因为HTTP/2还是基于TCP的,但是因为TCP的一些特性,例如握手过程、拥塞控制、丢包重传等,还是导致传输效率不高。而且很多网络中间设备,路由器、交换机等等,也不可能升级TCP协议,所以想通过优化TCP协议来提升传输效率是不可能的。
所以HTTP/3决定基于UDP协议来实现,又称为QUIC协议。实现了类似TCP的流量控制、数据重传可靠传输等功能,集成了TLS加密功能,实现了HTTP/2的多路复用功能,实现使用0-RTT或1-RTT来建立连接的快速握手功能。
不过目前HTTP/3还没有被大范围的支持。