HTTP协议
复习一下HTTP协议。
WEB服务
WEB是World Wide Web(万维网)的简称,是一种基于超文本和 HTTP 的、全球性的、动态交互的、跨平台的分布式图形信息系统。我们通常所说的 WWW 服务、Web 服务,其实是一个意思,泛指通过 HTTP 协议传输,使用图形化界面来展示信息的一种方式。也就是俗称的网站或者网页。
HTTP协议
HTTP协议,即超文本传输协议(HyperText Transfer Protocol),是基于TCP协议的应用层传输协议。
特点
-
采用Client/Server模式
-
简单快速
-
灵活
HTTP允许传输任意类型的数据对象。正在传输的类型由
Content-Type
加以标记。 -
无连接
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。早期这么做的原因是请求资源少,追求快。后来通过
Connection: Keep-Alive
实现长连接。 -
无状态
HTTP
协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。
HTTP/0.9
最早的HTTP版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET
。
GET /index.html
上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页index.html
。
协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。
<html>
<body>Hello World</body>
</html>
服务器发送完毕,就关闭TCP连接。
HTTP/1.0
简介
1996年5月,HTTP/1.0 版本发布,新增了大量内容。
-
1.0版本的协议可以发送任何格式的内容,使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。
-
新版本引入了
POST
命令和HEAD
命令,丰富了浏览器与服务器的互动手段。 -
请求和相应的格式有所改变。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
-
其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
请求格式
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
响应格式
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
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
,每个值包括一级类型和二级类型,之间用斜杠分隔。
客户端请求的时候,可以使用Accept
字段声明自己可以接受哪些数据格式。
Accept: */*
Content-Encoding 字段
由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding
字段说明数据的压缩方法。
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
客户端在请求时,用Accept-Encoding
字段说明自己可以接受哪些压缩方法。
Accept-Encoding: gzip, deflate
缺点
HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。
TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。
为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection
字段。
Connection: keep-alive
这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。
Connection: keep-alive
一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。
HTTP/1.1
1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。
持久连接
1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive
。
客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close
,明确要求服务器关闭TCP连接。
Connection: close
目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。
管道机制
1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。
Content-Length 字段
一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length
字段的作用,声明本次回应的数据长度。
Content-Length: 3495
上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。
在1.0版中,Content-Length
字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。
分块传输编码
使用Content-Length
字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。
对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。
因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked 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
0