本文主要的是从浏览器的角度来对HTTP相关的知识做一个浅显的讲解,如有不对,欢迎大家指正。
超文本传输协议 HTTP/0.9
首先我们来看看诞生最早的 HTTP/0.9。HTTP/0.9 是于 1991 年提出的,主要用于学术交流。
功能简单——用来在网络之间传递 HTML 超文本的内容,所以被称为 超文本传输协议。实现也很简单,采用了基于请求响应的模式,从客户端发出请求,服务器返回数据。
HTTP/0.9 请求流程 (如下图)
- 因为 HTTP 都是基于 TCP 协议的,所以客户端先要根据 IP 地址、端口和服务器建立 TCP 连接,而建立连接的过程就是 TCP 协议三次握手的过程。
- 建立好连接之后,会发送一个 GET 请求行的信息,如GET /index.html用来获取 index.html。服务器接收请求信息之后,读取对应的 HTML 文件,并将数据以 ASCII 字符流返回给客户端。
- HTML 文档传输完成后,断开连接。
HTTP/0.9 特点:
- 只有一个请求行, 没有请求头和请求体 , 因为只用请求行就可以表达客户端的需求。
- 服务器只返回数据,没有相应的响应头。
- 返回的文件以 ASCII 字节流传输(返回的数据也只有html文件,所以就 ASCII 比较合适。
需求推动下的 HTTP/1.0
随着网络的发展,浏览器中展示的不单是 HTML 文件了,还包括了 JavaScript、CSS、图片、音频、视频等不同类型的文件。因此需要支持多种类型的文件下载,而且文件格式不仅仅局限于 ASCII 编码,还有很多其他类型编码的文件,所以在曾经的那个时候,HTTP/0.9 已不能满足网络与日俱增的发展同 HTTP/0.9 只支持单一类型文件之间的矛盾,大家迫切需要一个新兴的协议来支撑新兴网络,这就是 HTTP/1.0 诞生的原因!
如何支持?
HTTP 是浏览器和服务器之间的通信语言,不过 HTTP/0.9 在建立好连接之后,只会发送类似GET /index.html的简单请求命令,并没有其他途径告诉服务器更多的信息,如文件编码、文件类型等。同样,服务器是直接返回数据给浏览器的,也没有其他途径告诉浏览器更多的关于服务器返回的文件信息。这种简单的交流型形式无疑不能满足传输多种类型文件的需求,那为了让客户端和服务器能更深入地交流,HTTP/1.0 引入了请求头和响应头,它们都是以为 Key-Value 形式保存的,在 HTTP 发送请求时,会带上请求头信息,服务器返回数据时,会先返回响应头信息。 HTTP/1.0 请求流程,如图。
HTTP/1.0 解决的问题:
- 浏览器需要知道返回的数据是什么类型的,根据不同的数据类型做针对性的处理。
- 由于文件增大,为了减轻传输性能,服务器会对数据进行压缩后再传输,所以浏览器需要知道服务器压缩的方法。
- 针对不同地区,浏览器要告诉服务器需要的语言版本。
- 浏览器需要知道文件的编码类型。
基于以上问题,HTTP/1.0 在发起请求时候会通过 HTTP 请求头告诉服务器它期待服务器返回什么类型的文件、采取什么形式的压缩、提供什么语言的文件以及文件的具体编码。最终发送出来的请求头内容如下:
accept: text/html
accept-encoding: gzip, deflate, br
accept-Charset: ISO-8859-1,utf-8
accept-language: zh-CN,zh
服务器会根据请求头的信息来准备响应数据。不过有些情况下会存在意外,比如浏览器请求的压缩类型是 gzip,但是服务器不支持 gzip,只支持 br 压缩,那么它会通过响应头中的 content-encoding 字段告诉浏览器最终的压缩类型,也就是说最终浏览器需要根据响应头的信息来处理数据。下面是一段响应头的数据信息
content-encoding: br
content-type: text/html; charset=UTF-8
有了响应头的信息,浏览器就会使用 br 方法来解压文件,再按照 UTF-8 的编码格式来处理原始文件,最后按照 HTML 的方式来解析该文件。
HTTP/1.0 其他特性:
- 响应行引入状态码,告知浏览器请求状态
- HTTP?1.0 新增 Cache 机制, 用作缓存数据
- 请求头中新增 用户代理 (user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36) 字段, 告知服务器 客户端 信息。
进一步改进的 HTTP/1.1
1、改进持久链接
HTTP/1.0 每进行一次 HTTP 通信,都需要经历建立 TCP 连接、传输 HTTP 数据和断开 TCP 连接三个阶段,随着文件的增多,如果每个请求都经过链接、传输数据和断开链接的过程,这会增大很大的网络开销。
HTTP/1.1 中增加了持久连接的方法,它的特点是在一个 TCP 连接上可以传输多个 HTTP 请求,只要在一段时间内浏览器或者服务器没有明确断开连接,那么该 TCP 连接会一直保持。这样可以减少服务器的负担,并降低整体的请求时长。持久连接在 HTTP/1.1 中是默认开启的,所以你不需要专门为了持久连接去 HTTP 请求头设置信息,如果你不想要采用持久连接,可以在 HTTP 请求头中加上Connection: close。目前浏览器中对于同一个域名,默认允许同时建立 6 个 TCP 持久连接。 HTTP/1.1 如下图
\
2、不成熟的管线化
HTTP/1.1 虽然减少了 TCP 的连接和断开次数,但是每个请求之间是串行的, 需要等待上一个返回后,才能进行下一次请求, 一个请求如果因为丢包等问题中断的话,就会阻塞后面的请求,这也是常说的队头阻塞。
HTTP/1.1 中试图通过管线化的技术来解决队头阻塞的问题。HTTP/1.1 中的管线化是指将多个 HTTP 请求并发提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。FireFox、Chrome 都做过管线化的试验,但是由于各种原因,它们最终都放弃了管线化技术。
3、虚拟主机(域名分片)
在 HTTP/1.0 中,每个域名绑定了一个唯一的 IP 地址,因此一个服务器只能支持一个域名。但是随着虚拟主机技术的发展,需要实现在一台物理主机上绑定多个虚拟主机,每个虚拟主机都有自己的单独的域名,这些单独的域名都公用同一个 IP 地址。因此,HTTP/1.1 的请求头中增加了 Host 字段,用来表示当前的域名地址,这样服务器就可以根据不同的 Host 值做不同的处理。
4、对动态内容的支持, 分块传输
HTTP/1.1 通过引入 Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持。
Web服务器有时生成HTTPResponse无法在Header就确定消息大小的,这时一般来说服务器将不会提供Content-Length的头信息,而采用Chunked编码动态的提供body内容的长度。\
进行Chunked编码传输的HTTP Response会在消息头部设置:
Transfer-Encoding: chunked
5、缓存安全机制
HTTP/1 就先介绍到这里,谢谢观看~