HTTP协议(上)

Posted Turbo的札记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP协议(上)相关的知识,希望对你有一定的参考价值。

本文沿时间线介绍了HTTP具有的特性与功能,具体使用方法——HTTP请求与响应的内容将会在中篇介绍。

全称HyperText Transfer Protocol(超文本传输协议)。

协议应用场景/传输的过程:客户端向服务端发送请求,服务端收到请求进行一定处理后将结果返回给客户端,期间两次信息传递依照协议标准。
HTTP协议永远都是客户端发起请求,服务器回送响应,服务器无法自行将消息推送给客户端。

规定了客户端与服务端进行数据交互的通信格式,默认使用80端口,最常见的就是浏览器(客户端)向服务器(服务端)请求数据传递数据。
基于TCP/IP通信协议来传递数据,所有www文件都必须遵守这个标准。
HTTP协议是一个无状态的协议,同一个客户端的这次请求和上次请求没有对应关系。

www:万维网WWW是World Wide Web的简称,也称为Web、3W等。WWW是基于客户机/服务器方式的信息发现技术和超文本技术的综合。WWW服务器通过超文本标记语言(html)把信息组织成为图文并茂的超文本,利用链接从一个站点跳到另个站点。这样一来彻底摆脱了以前查询工具只能按特定路径一步步地查找信息的限制。

1.HTTP/0.9版

1991年发布HTTP协议0.9版,该版本仅有一个 GET 命令。

GET/index.html

上面示例命令表示,TCP连接建立后,客户端向服务器请求网页文件index.html。


2.HTTP/1.0版

1996年5月,HTTP/1.0版本发布。

可以发送任何内容,文字、图像、视频、二进制文件。

命令:GET 、POST 、HEAD。

请求和回应的格式变了:除了数据部分,每次通信还包括头部信息(用来描述一些元数据)。
新增功能:

状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)。

缺点:

每个TCP链接只能发送一个请求,发送数据完毕,连接就关闭,如果还要请求其它资源,就必须再新建一个连接,而TCP链接建立的成本很高(三次握手),并且开始发送速率比较慢,所以性能很差。

为了解决这个问题,有些浏览器在请求时用了一个非标准的 Connection 字段:Connection:keep-alive。这个字段字段要求服务器不关闭TCP连接,直到客户端不再使用该字段,连接就会关闭。


上面两个都是历史了,不详细展开,了解即可。

3.HTTP/1.1
1997年1月发布,直到今天依旧流行。
新增命令:PUT、PATCH、HEAD、OPTIONS、DELETE。
客户端头信息新增了Host字段,用来指定服务器的域名。
持续连接:

TCP连接默认不关闭,可以被多个请求重复使用,不用声明Connection:keep-alive。客户端和服务器发现对方一段时间没有活动,连接会被自动关闭,不过规范的做法是在客户端最后一个请求时发送 Connection:close。目前对同一个域名,大多数浏览器允许同时建立6个持久连接。

管道机制:

同一个连接里可以同时发送多个请求,即客户端发送A请求后无需等待服务器回应可以立刻发送B请求,服务器还是按照顺序,先回应A请求再回应B。

Content-Length 字段:

声明本次回应的数据长度,用于区分一次TCP连接中多次请求对应的回应的数据包。1.0版中因为TCP连接在一次请求回应后连接会关闭,所以该字段不是必需的。示例:下面代码告诉浏览器本次回应的长度时3495字节,后面的字节就属于下一个回应。

Content-Length: 3495

分块传输编码:

使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度;对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。

更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer);因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成;每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。

下面是一个例子。

HTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunked
25This is the data in the first chunk
1Cand this is the second one
3con
8sequence
0

缺点:

虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。
为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。
4.HTTP/2
2015年发布,之所以不叫HTTP/2.0,是因为标准委员会不打算再发布子版本,下一个标准将是HTTP/3。
二进制协议:
HTTP/1.1 版的头信息肯定是(ASCII编码的)文本,数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。
二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
多工:
HTTP/2复用TCP连接,在一个连接里,可以同时发送和多个请求和回应,并且不用按照顺序一一对应,这样就避免了“队头堵塞”。
继续之前的例子:在HTTP/1.1中,客户端先后发送A、B两个请求,服务端要按顺序一次回应,但在HTTP/2中,如果处理生成A对应结果很费时,服务器可以发送A请求处理好的部分,一边继续处理A的结果,一边将B的请求回应,等A剩余部分的结果得到后再发送A请求剩下的部分。你可以理解成餐厅服务员拿到A顾客的点菜单提交给厨房后,并不会等才做好并上菜后再去招待另一位顾客,而是去拿B顾客的点菜单。

这样多个事件占用同一条通道的通信,就叫做多工。

数据流:

由前面多工可知,HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
概念:HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
数据流的优先级:客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
数据流的取消:数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。
头信息压缩:
HTTP协议不带有状态,每次请求都必须附上所有信息。所以很多字段都是重复的,比如Cookie和User Agent,浪费带宽影响速度。
HTTP/2对此进行了优化,引入了头部信息压缩机制:一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不用发送同样字段了,只发送索引号。
服务器推送:

文首说过HTTP协议只能是服务端相应客户端,但HTTP/2允许服务端未经请求,主动向客户端发送资源,这叫服务器推送(sever push)。
常见场景:客户端请求一个网页,这个网页里面肯定还包含很多静态资源,一般是客户端收到网页解析加载HTML文件发现静态资源,再发送静态资源请求。其实服务器可以预期到客户端请求网页后还会请求网页里的静态资源,所以就主动把这些静态资源随着网页一起发给客户端。



本文为以阮一峰博客(http://www.ruanyifeng.com/blog/2016/08/http.html)为主要参考资料学习后所整理的笔记。

以上是关于HTTP协议(上)的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 报错 DioError [DioErrorType.DEFAULT]: Bad state: Insecure HTTP is not allowed by platform(代码片段

CPNtools协议建模安全分析---实例变迁标记

HTTP客户端代码片段

如何使用 Android 片段?

Android 片段和活动

代码适用于与单个 html 文件不同的堆栈片段