HTTP
协议工作于C/S
架构上,是万维网服务器传输超文本到本地客户端的一种应用层协议,全称是:Hyper Text Transfer Protocol
(超文本传输协议),HTTP
是基于TCP/IP
通信协议来传递数据的。HTTP
于1990
年被提出,由于其简洁性、快速性等特点,被广泛应用,并且经过不断的完善和发展,功能也越来越强大,目前已经发展到HTTP/2
版本。
一. HTTP/0.9
最早版本发布于1991
年,功能极其简单,不涉及数据包的传输,默认使用80端口,只有一个GET
请求方法,且服务器只能响应HTML
格式的字符串,服务器响应后即关闭连接。
请求:
GET /index.html
响应
<html>
<body>
hello world
</bocy>
</html>
二. HTTP/1.0
1996
年5
月,HTTP/1.0
发布,引入了POST
和HEAD
命令,大大增强了交互功能,任何格式的内容都可以发送,为互联网的大发展奠定了基础;同时,除了数据部分,每次通信还要求包含头信息(HTTP header
),来描述一些meta
数据。
新增功能还包括:状态吗(status code
)、多字符集支持、多部分发送(multi-part type
)、权限(authorization
)、缓存(cache
)、内容编码(content encoding
)等。
请求格式:
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)
Accept: */*
可以看到,请求行末尾添加了协议版本号,后面是协议头的信息,描述客户端的情况。
其中,Accept: */*
表明客户端接收任何类型的数据
响应格式:
HTTP/1.0 304 Not Modified
Cache-Control max-age=0, must-revalidate
Date Fri, 10 Feb 2017 06:24:38 GMT
Server apache
Connection Keep-alive
<html>
<body>
hello world
</body>
</html>
可以看到回应的数据的:头信息 + 一个空行 + 数据。其中,第一行是状态行,格式为:协议版本 + 状态码 + 状态描述。
常用字段介绍:
1. Content-Type
1.0
版规定,头信息必须是ASCII码,后面的数据可以是任何格式,因此,服务器在响应的时候,也要告诉客户端,数据是什么格式。下面是Content-Type
字段的常用值:
text/plain
text/html
text/css
image/jpeg
image/png
image/svg+xml
audio/mp4
video/mp4
application/javascript
application/pdf
application/zip
application/atom+xml
另外,这些数值统称为MIME type
,每个值包括一级类型和二级类型,之间用斜杠分隔,用户也可以自定义该类型,还可以在尾部使用分号,添加参数。
Content-Type: text/html; charset=utf-8
上面的代码表示,发送的是网页,并且编码是的UTF-8格式。
Accept: */*
上面的代码表示客户端可以接受任何格式的数据。
2. Content-Encoding
发送的数据还可以被压缩后再发送,该字段说明了数据压缩的方法。
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
客户端还可以在请求时,用Accept-Encoding
字段说明自己可以接受哪些压缩方法。
Accept-Encoding: gzip, deflate
缺点
HTTP/1.0
版的主要缺点是,由于TCP
的每次连接都需要客户端和服务端进行3
次握手,但是连接成功后只能发送一次请求,然后连接就断开了,如果需要多次请求,这样效率就很低。但是,为了解决多次请求效率低下的问题,有一个非标准的connection
字段暂时解决了该问题。
Connection: keep-alive
这样就可以复用TCP
连接,直到客户端或者服务端主动关闭连接。但是这不是标志字段,不同的实现可能行为不一致,所以是一种暂时的解决方案。
三. HTTP/1.1
1997
年1
月,HTTP/1.1
版本发布,它进一步完善了HTTP
协议,一直到今天还在使用,是最流行的版本;HTTP/1.1
新增了许多特性:
新增功能介绍:
1.持久连接
HTTP/1.1
默认TCP
连接不关闭,可以被多个请求复用,不用声明Connection: keep-alive
。客户端可以在最后一个请求时,主动发送Connection: close
,明确要求服务器关闭TCP
连接,或者不发送,那么客户端和服务器发现对方一段时间没有活动,就会主动关闭连接。目前,对于同一个域名,大多数浏览器允许同时建立6
个持久连接。
Connection: close
2.管道机制
HTTP/1.1
引入了管道机制(pipelining
),即在同一个TCP
连接里面,客户端可以同时发送多个请求,这样只是改进了客户端HTTP
协议请求的效率,服务器还是按照请求的先后顺序来响应。
3.Content-Length
Content-Length
字段显示本次响应的数据长度,如果数据被压缩,则是压缩后的长度。在Connection: keep-alive
条件下,Content-Length
是必须的;反之,和HTTP/1.0
一样,Content-Length
不是必须的。
4.分块传输编码
使用Content-Lenght
字段的前提条件是,服务器发送响应之前,必须知道响应的数据长度。但是,对于一些耗时的动态操作来说,服务器要等到所有操作完成后,才能发送数据,效率不高。因此,HTTP
采用了“流模式(stream
)”,即“分块传输编码”(chunked transfer encoding
)方式,表明响应的数据长度未定,这样就可以产生一块数据,就发送一块数据,提高服务器的响应效率。
Transfer-Encoding: chunked
这样,只要请求或响应的头信息里有Transfer-Encoding
字段,就表明响应将由数量未定的数据组成。
每个非空的数据块之前,都会有一个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
5.其它特性
新增了许多的请求方式:PUT
、PATCH
、OPTIONS
、DELETE
、TRACE
,还增加了Host
字段,用来指定服务器的域名,就可以把同一请求发送给不同的网站,为虚拟主机的发展奠定了基础。
缺点
虽然HTTP/1.1
版允许复用TCP
连接,但是同一个TCP
连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着,这称为"队头堵塞"(Head-of-line blocking
)。
为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS
代码、域名分片(domain sharding
)等等。如果HTTP
协议设计得更好一些,这些额外的工作是可以避免的。
四. HTTP/2
2015年,HTTP/2发布,主要解决了HTTP1.1
的效率不高的问题,新增了二进制协议、多工、数据流、头信息压缩等等功能,具体介绍如下:
1.二进制协议
HTTP/2
是一个彻底的二进制协议,头信息和数据都是二进制,统称为帧(frame
):头信息帧和数据帧。二进制的优势是:可以定义额外的帧,以适应未来更高级的应用。
2.多工
HTTP/2
复用TCP
连接,客户端和服务器都可以同时发送多个请求或响应,不用按照顺序一一对应,避免了对头堵塞,实现了双向的、实时的通信。
3.数据流
HTTP/2
定义每个请求或响应的所有数据为一个数据流(stream
),每个数据流都有一个唯一的编号,数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。协议规定:客户端发出的数据流的ID位奇数,服务器发出的数据流ID为偶数。
另外,数据流发送过程中,客户端和服务器都可以随时发送信号而不用关闭TCP
连接,以便其它请求使用。但是HTTP1.1
就不行,它取消请求的方式必须的关闭连接。HTTP/2
还指定了数据流的优先级,优先级越高,服务器就优先处理。
4.头信息压缩
HTTP
协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie
和User Agent
,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。
HTTP/2
对这一点做了优化,引入了头信息压缩机制(header compression
)。一方面,头信息使用gzip
或compress
压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
5.服务器推送
HTTP/2
允许服务器主动向客户端发送资源,主要是服务器经过预测,把一些客户端可能请求的资源主动发送给客户端,提高用户体验。
本文主要参考阮一峰的
HTTP协议入门
,版权归阮一峰所有。
参考资料