HTTP协议是什么?
HTTP协议全称为超文本传输协议(HyperText Transfer Protocol),它是基于TCP协议的应用层传输协议,简单来说就是客户端与服务器端进行数据传输的一种规则。
HTTP是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。
HTTP/0.9
HTTP/0.9是最早的一个版本,在1991年发布,只有GET一种请求方法,并且不支持请求头。只支持纯文本一种内容,服务器只能响应HTML格式的字符串,且不能插入图片。HTTP/0.9具有典型的无状态、无连接特性。
HTTP/1.0
HTTP/1.0协议是HTTP协议的第二个版本,于1996年发布,如今仍然被广泛地使用,尤其是在代理服务器中。是一种无状态、无连接的应用层协议。
-
增加POST、HEAD等请求方法。
-
引入头部信息。除了要传输的数据之外,每次通信都包含头信息,用来描述一些信息。
-
传输数据格式不再局限于HTML格式。根据Content-Type可以支持多种数据格式,这使得互联网不仅可以用来传输文字,还可以传输图像、音频、视频等二进制文件。
-
引入cache缓存机制。
-
引入状态码。
HTTP/1.0规定客户端与服务器之间保持短暂的连接,每个TCP连接只能发送一个请求,当服务器响应后就会关闭这个TCP连接,下一次请求需要再次建立TCP连接。TCP连接建立的成本很高,因为需要客户端和服务器端进行三次握手。因此当一个网页需要发送多个HTTP请求时,就会造成性能问题。
其次就是队头阻塞。由于HTTP/1.0规定下一个请求必须在前一个请求响应到达之前才能发送,若前一个请求响应一直不到达,那下一个请求就不发送,同样后面的请求也被阻塞了。
为解决这些问题,HTTP/1.1出现了。
HTTP/1.1
为解决HTTP/1.0短连接造成的性能开销,HTTP/1.1引入了持久连接。
- 引入持久连接(即长连接) 。可以通过设置
connection: keep-alive来保持HTTP连接不断开。避免了每次客户端与服务器端请求都要重复建立释放连接,一个TCP连接可以被多个请求复用,提高了网络的利用率。客户端和服务器端发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求是,发送connection: false来明确要求服务器关闭TCP连接。
-
加入管道机制。基于
HTTP/1.1的长链接,在同一个TCP连接里,允许多个请求同时发送,使得请求管道化成为可能。管道化使得请求能够“并行“传输。举个例子,假设客户端需要请求两个资源。以前的做法是,在同一个TCP连接里,先发送A请求,然后等待服务做出响应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但服务器还是按照请求顺序,先响应A请求,再响应B请求,所以这并不是真正意义上的并行传输。现阶段的浏览器厂商实现并行传输,采用的做法是允许我们打开多个TCP会话,这就是我们所熟悉的浏览器对同一个域下能够并行加载6~8个资源的限制。
-
Content-length字段。因为现在一个TCP连接可以传送多个回应,那么就要有一种机制,来区分数据包是属于哪一个回应的,这就是Content-length字段的作用,用来声明本次回应的数据长度。 -
分块传输编码。使用
Content-length字段的前提条件是,服务器发送响应之前,必须知道响应的数据长度。对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用“流模式”(stream),取代“缓存模式”(buffer)。因此,1.1版本规定可以不是使用Content-Length字段,而使用“分块传输编码”(chunk transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明响应将由数量未定的数据块组成。Transfer-Encoding: chunked // 分块传输每一个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完毕,例子如下:
HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked 25 This is the data in the first chunk 1C and this is the second one 3 con 8 sequence 0 -
新增了请求方式PUT、PATCH、OPTIONS、DELETE等。
-
增加cache缓存策略,如Etag、If-Unmodified-Since、If-Match、If-None-Match等可供选择的了缓存头来控制缓存策略。
-
客户端请求的头信息新增了Host字段,用来指定服务器的域名。
-
HTTP/1.1支持文件断点续传,RANGE:bytes,HTTP/1.0每次传送文件都是从文件头开始,即0字节处开始。RANGE:bytes=XXXX表示要求服务器从文件XXXX字节处开始传送,断点续传。即返回码是206(Partial Content)
HTTP/2.0
-
二进制分帧:
HTTP/1.1版本的头信息必须是文本(ASCII编码),数据体可以是文本,也可以是二进制,HTTP/2.0则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为“帧”(frame):头信息帧和数据帧。那么如何在不改动HTTP/1.1的语义、方法、状态码、URI以及首部字段等请情况下,将HTTP/1.1过渡到HTTP/2.0呢?关键之一就在于在应用层(HTTP/2.0)和传输层(TCP or UDP)之间增加一个二进制分帧层。在二进制分帧层中,HTTP/2.0会将所有传输的信息分割为更小的信息并封装在帧中,并对他们采用二进制格式的编码。
-
多路复用(连接共享) :
HTTP/2.0版本会复用TCP连接。在一个连接里,客户端和服务器端都可以同时发送多个请求或响应,而且不用按照顺序一一对应,这样就避免了“队头阻塞”。下面是几个概念:
- 流(stream):已建立连接上的双向字节流。
- 消息:与逻辑消息对应的完整的一系列数据帧。
- 帧(frame):
HTTP/2.0通信的最小单位,每个帧包含帧头部,至少会标识出当前帧所属的流(stream id)。下面是帧的结构:
帧的字节中保存了不同的信息,前9个字节对于每个帧都是一致的,服务器解析HTTP/2.0的数据帧是,只需要解析这些字节,就能准确的指导整个镇期望多少字节数来进行处理信息,先了解一下帧中每个字段所代表的信息:
| 名称 | 长度 | 描述 |
|---|---|---|
| Length | 3 字节 | 表示帧负载的长度,默认最大帧大小2^14 |
| Type | 1 字节 | 当前帧的类型,下面会做介绍 |
| Flags | 1 字节 | 具体帧的标识 |
| R | 1 字节 | 保留位,不需要设置,否则可能带来严重后果 |
| Stream Identifier | 31 位 | 每个流的唯一ID |
| Frame Payload | 3 字节 | 真实帧的长度,真实长度在Length中设置 |
下面是HTTP/2.0数据传输图示:
从图中可见,所有的HTTP/2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流。
每个数据流以消息的形式发送,而消息由一个或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的stream id标识符来重新组装。
举个例子,每个请求是一个数据流,数据流以消息的方式发送,而消息又分为多个帧,帧头部记录着stream id用来标识当前帧所属的数据流,不同属的帧可以在连接中混杂在一起。接收方可以根据stream id将帧再归属到各自不同的请求中去。
另外,多路复用(连接共享)可能会导致关键请求被阻塞。HTTP/2.0里每个数据流都可以设置优先级和依赖,优先级高的数据流会被服务器优先处理和返回给客户端,数据流还可以依赖其他的子数据流。
可见,HTTP/2.0实现了真正的并行传输,它能够在一个TCP连接上进行任意数量的请求,而这个强大的功能则是基于“二进制分帧”的特性。
-
头部压缩:在
HTTP/1.x中,头部元数据都是以纯文本的形式发送的,通常会给每个请求增加500~800字节的负荷。因为HTTP协议是无状态的,所以每次请求都必须带上所有信息。所以请求的很多字段都是重复的,比如Cookie和UserAgent,一模一样的内容,每次请求都必须携带,这会浪费很多带宽,也影响传输速度。
HTTP/2.0对这一点做了优化,引入头信息压缩机制(header compression)。一方面,头信息用gzip或compress压缩后再发送;另一方面,客户端和服务器端同时维护一张头信息表,所有的字段都会存入这个表,生成一个索引号,以后就不发送同样的字段了,只发送索引号,减少了需要传输的数据大小。 -
服务器推送:
HTTP/2.0允许服务器不需要客户端的请求就可以主动向客户端发送资源。 -
流量控制: HTTP/2.0不同于HTTP/1.1的只要客户端可以处理,服务端就会尽可能快地发送数据。HTTP/2.0提供了客户端调整传输速度的能力(服务端也可以),在每一个数据帧中告诉对方,发送方想要接受多少字节的数据。
总结
HTTP/0.9:功能简陋,只支持GET方法,只能发送HTML格式字符串。
HTTP/1.0:无状态、无连接,支持多种数据格式,增加POST、HEAD等方法,增加头信息,每个TCP连接只能发送一个http请求(无持久连接)
HTTP/1.1:默认持久连接、请求管道化、增加缓存处理、增加Host字段、支持断点传输分块传输等。
HTTP/2.0:二进制分帧、多路复用、头部压缩、服务器推送、流量控制。
参考文章