1
计算机网络技术理论与实践
1.9.3.1 8.3.1 HTTP协议原理

8.3.1 HTTP协议原理

1.连接方式

HTTP既可以使用非持久连接(Nonpersistent Connection),也可以使用持久连接(Persistent Connection)。HTTP/1.0只支持非持久连接,而HTTP/1.1默认使用持久连接。

(1)非持久连接

假设某Web页面由1个基本HTML文件和10个JPEG图像构成,所有这些对像都存放在同一台服务器上。基本HTML文件的URL为:www.sina.com/somepath/index.html。在非持久连接情况下,从客户端向服务器请求一个Web页面的步骤如下:

①HTTP客户端初始化一个与HTTP服务器www.sina.com的TCP连接。HTTP服务器使用默认端口号80监听来自HTTP客户端的连接请求。

②HTTP客户端通过与TCP连接相关联的本地套接字发出一个HTTP请求消息。这个消息中包含所请求对象的路径名:/somepath/index.html。

③HTTP服务器从与TCP连接相关联的本地套接字接收这个请求消息,再从服务器的内存或硬盘中取出对象/somepath/index.html,并通过同一套接字发出包含该对象的响应消息。

④HTTP服务器关闭这个TCP连接(客户端收到前面的响应消息之后才会真正终止这个连接)。

⑤HTTP客户端从套接字接收到这个响应消息,TCP连接随后终止。响应消息表明其中的对象是一个HTML文件。客户端从响应消息中取出这个文件,分析后发现其中包含对10个JPEG对象的引用。

⑥对每一个引用的JPEG对象重复步骤①~④。

上述步骤之所以称为非持久连接,因为每次服务器发出一个响应消息后,相应的TCP连接就被关闭,也就是说每个TCP连接只用于传输一个请求消息和一个响应消息。就上述例子而言,用户每请求一次Web页面,就会产生11个TCP连接,造成非常大的带宽资源浪费,也延长了消息响应的时间。

当前大多数浏览器允许用户通过配置来控制并行TCP连接的数量。通常浏览器默认可以打开5~10个并行的TCP连接,每个连接处理一个请求—响应事务,使用并行连接可以缩短响应时间。用户可以把最大并行连接数设为1,此时这10个JPEG图像的连接是串行建立的。

(2)持久连接

非持久连接存在许多缺陷:首先,客户端需要为每个待请求的对象建立并维护一个新的TCP连接。对于每个连接,TCP都需要在客户端和服务器端分配TCP缓冲区,并维持TCP变量。有的Web服务器可能同时为来自数百个不同客户端的请求提供服务,这种方式会严重增加其负担。其次,每个对象都有2个RTT(往返传输时间)的响应时延,一个RTT用于建立TCP连接,另一个RTT用于请求和接收对象。最后,每次请求对象时都会遇到TCP慢启动,因为每个TCP连接都起始于慢启动阶段。

由于非持久连接的这些缺陷,HTTP/1.1协议中采用了持久连接。在持久连接下,服务器在发出响应后会保持TCP连接。同一对客户端与服务器之间的后续请求和响应可以通过这个TCP连接继续发送。整个Web页面(上例中为包含一个基本HTML文件和10个图像的页面)可以通过单个持久TCP连接发送,甚至存放在同一台服务器中的多个Web页面也可以通过单个持久TCP连接发送。通常,HTTP服务器在某个TCP连接闲置一段特定时间后才会关闭它,这段时间是可以配置的。

2.身份认证和Cookie

HTTP服务器是无状态的,这样可以简化服务器端程序的设计,以便开发出更高性能的Web服务器软件。但是,Web服务器经常会有标识其用户的需求,例如Web服务器可能希望限制某些用户的访问,也可能想要根据用户的身份来提供相应的内容。HTTP提供了两种帮助Web服务器标识用户的机制:身份认证和Cookie。

(1)身份认证

许多Web站点要求用户提供一个(用户名,口令)对,才能访问存放在其Web服务器中的资源。这种方式称为身份认证(authentication)。HTTP提供特殊的状态码和头部来帮助Web站点执行身份认证过程。下面通过一个例子来了解这些特殊的状态码和头部是如何工作的。

假设有一个HTTP客户端在请求某个HTTP服务器上的一个对象,而该服务器要求用户拥有访问权限。

HTTP客户端首先发送一个不含特殊头部的普通请求消息。HTTP服务器以空的附属体和一个“401Authorization Required”状态码作为响应。HTTP服务器还在这个响应消息中包含WWW-Authenticate头部,说明具体如何执行身份认证,这个头部通常告诉用户需要提供一个(用户名,口令)对。

HTTP客户端收到这个响应消息后提示用户输入用户名和口令,然后重新发送请求消息。这个请求消息具有了一个Authorization头部,其中包含有用户输入的用户名和口令。

取得第一个对象后,HTTP客户端在请求该服务器上对象的后续请求中会继续发送这个(用户名,口令)对,这将持续到用户关闭浏览器为止。在浏览器未被关闭前,这个(用户名,口令)对是缓存在高速缓冲区中的,因此,浏览器不会每请求一个对象就提示用户输入一次用户名和口令。通过上述方式,要求用户拥有访问权限的Web站点就能标识出每个请求的用户。

(2)Cookie

Cookie是一种可让Web站点跟踪用户的候选机制,定义在RFC 2109中。有些Web站点使用Cookie,有些则不用。下面通过一个例子了解Cookie的工作原理。

假设一个HTTP客户端首次向一个使用Cookie的Web站点发出请求消息。Web服务器会在其响应消息中包含一个Set-Cookie的头部。该头部的值可以是一个由Web服务器产生的客户标识数,例如,Set-Cookie:1678453。

HTTP客户端收到这个响应消息后,取出Set-Cookie头部中的标识数,并在HTTP客户端主机上的某个特殊Cookie文件中,添加新的一行来保存这条信息。这行信息中一般包含服务器主机的主机名和与用户关联的标识数。在一段时间(如一个星期)之内,当同一个用户启动的新HTTP客户端向同一台Web服务器发送请求时,会在请求消息中包含一个Cookie头部,其值为早先由该Web服务器产生的标识数,例如,Cookie:1678453。

在这种方式中,Web服务器并不知道提出请求的用户的用户名,但是它确实知道该用户与之前提出请求的用户是同一个。通常在Windows系统中,Cookie文件存放在C:\Documents and Settings\(user)\Cookies目录中。

当前,越来越多的Web服务器使用Cookie来标识用户,以完成一些特殊的目的:

·如果Web服务器要求身份认证,但又不想让同一用户每次访问本Web站点时都输入用户名和口令,可以设置一个Cookie。

·如果Web服务器想要记住用户的偏好,以便在他们后续访问中有目的地提供广告,可以设置一个Cookie。

·如果Web站点提供购物服务,Web服务器可以使用Cookie跟踪用户购买的物品,也就是建立一个虚拟的购物车。当用户将物品放入购物车后,即使退出了浏览器,下次登录后,物品仍然在购物车中,不需要重新选购。

3.HTTP消息格式

HTTP规范1.0[RFCl945]和1.1[RFC 2616]定义了HTTP消息的格式。HTTP消息分为请求消息和响应消息两类。下面分别进行介绍。

(1)HTTP请求消息

下面是一个典型的HTTP请求消息:

GET/somedir/index.html HTTP/1.1

Host:www.sina.com

Connection:close

User-agent:Mozilla/5.0

Accept-language:zh-cn

(额外的回车符和换行符)

通过这个请求消息,可以看出:首先,HTTP消息是用普通的ASCII文本书写的。其次,这个消息共有5行(每行以一个回车符和一个换行符结束),最后一行后面还有额外的一个回车符和换行符。一个请求消息可以有更多行,也可以只有一行。请求消息的第一行称为请求行(Request Line),后续各行都称为头部行(Header)。

请求行有3个字段:方法字段、URL字段、HTTP版本字段。方法字段有多个值可供选择,包括GET、POST和HEAD。HTTP请求消息绝大多数使用GET方法,这是浏览器用来请求对象的方法,所请求的对象在URL字段中标识。本例中浏览器在请求对象/somedir/index.html。版本字段是显示当前所使用HTTP协议的版本信息,本例中浏览器采用的是HTTP/1.1版本。

头部行Host:www.sina.com存放请求对象所处的主机。请求消息中包含头部行Connection:close是在告知服务器本浏览器不使用持久连接,服务器发出所请求的对象后应关闭TCP连接。虽然浏览器实现的是HTTP/1.1版本,但是它也可以选择使用非持久连接。User-agent头部行指定用户代理,也就是发出当前请求的浏览器的类型,本例中的用户代理是Mozilla/5.0,它是Firefox浏览器的某个版本。Web服务器可以根据用户代理的类型给其发送同一个对象的不同版本。最后,Accept-language头部行指出如果所请求的对象有简体中文版本,那么服务器应该给用户发送这个版本;如果没有此版本,那么服务器应该发送其默认版本。

(2)HTTP响应消息

下面是一个典型的HTTP响应消息:

HTTP/1.1 200 0K

Connection:close

Date:Thu,13Oct 2011 10:15:20GMT

Server:Apache/2.2.6(Unix)

Last—Nodified:Mon,22Jun 2010 20:10:15GMT

Content—Length:6636

Content—Type:text/html

(数据数据数据数据数据……)

这个响应消息分为3部分:1个起始的状态行(Status Line)、6个头部行、1个包含所请求对象本身的附属体。

状态行有3个字段:协议版本字段、状态码字段、原因短语字段。本例的状态行表明,服务器使用HTTP/1.1版本,响应过程完全正常,也就是说服务器找到了所请求的对象,并正在发送。

HTTP服务器使用Connection:close头部行告知HTTP客户端,自己将在发送完本响应消息后关闭TCP连接。Date头部行指出HTTP服务器创建并发送本响应消息的日期和时间采用的是GMT时间(格林威治标准时间)。这个时间不是对象本身的创建时间或最后修改时间,而是服务器把该对象从其文件系统中取出,插入响应消息中发送出去的时间。Server头部行指出本消息是由Apache服务器产生的,服务器的版本号是2.2.6,运行于Unix主机上;它与HTTP请求消息中的User-agent头部行类似。Last-Nodified头部行指出对象本身的创建或最后修改日期和时间也采用GMT时间,对于对象的高速缓存至关重要。Content-Length头部行指出所发送对象的字节数。Content-Type头部行指出包含在附属体中的对象是HTML文本文件。对象的类型是由Content-Type头部行而不是由文件扩展名标识的。