最近看到http2协议,一直以来对网络的知识都是一知半解,现在想想,简直搞不懂以前上网络课的时候学了什么~ 看来是时候深入了解一下HTTP协议了~
http协议是基于tcp/ip协议之上的应用层协议,是一个无状态协议。
HTTP0.9
这是最早版本的http协议,这时候的协议还极其简单,只有一个get方法。服务器只能回应HTML格式的字符串,不能回应别的格式
http1.0
这时候可以发送任何格式的内容了。还引入了post 和 head 命令,http请求和响应报文的格式也发生了较大的改变,除了数据之外,额外增加了http header。也新增了许多功能包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。
为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。这个字段要求服务器不要关闭tcp连接,直到被主动关闭,但是它不是根本的解决办法,所以有http1.1横空出世啦~
http1.1
这一版本最大的变化是实现了持久化的连接,即tcp默认不关闭,但是这个持久化和WebSockets的持久化连接是不一样的注意区分。目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。
新增管道机制,即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。
Content-Length 字段 一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。
1.1版还新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。
但是在在一个TCP连接中,数据通信依然是按照顺序进行的,只有前一个回应传回来了才能发送下一个请求,这就可能造成对头堵塞。
HTTP2
HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”(frame):头信息帧和数据帧。
HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”。
在HTTP/2中,将所有的请求或者回应的数据包,成为一个数据流,每个数据流都有独一无二的编号来指出他们属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
服务器推送 HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。
常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。划重点,这里的服务器推送和WebSockets里的推送有本质上的区别。