配色: 字号:
2.2Web应用和HTTP协议
2014-06-20 | 阅:  转:  |  分享 
  
第二章应用层



2.2Web应用和HTTP协议



2.2.1HTTP概况



Web的应用层协议是超文本传输协议(HyperTextTransferProtocol,HTTP),它是Web的核心,在[RFC1945]和[RFC2616]中进行了定义。HTTP协议由两部分程序实现:一个客户机程序和一个服务器程序,它们运行在不同的端系统中,通过交换HTTP报文进行会话。HTTP定义了这些报文的格式以及客户机和服务器是如何交换报文的。



Web中常用的术语:Web页面(Webpage)是由对象组成的。对象(object)简单来说就是文件,如基本HTML文件、JPEG图形文件、Java小程序或视频片段文件,如果一个Web页面包含HTML文本和5个JPEG图形文件,那么这个Web页面有6个对象。这些文件通过一个URL地址寻址。每个URL地址由两部分组成:存放对象的服务器主机和对象的路径名。例如:http://www.aaa.com/aaa/bbb.jpg中的www.aaa.com是主机名,aaa/bbb.jpg是路径名。Web浏览器实现了HTTP的客户机端。Web服务器用于存储Web对象,实现了HTTP得服务器端。



HTTP定义了Web客户机是如何向Web服务器请求Web页面。当用户请求一个Web页面时,浏览器向服务器发出对该页面中所包含对象的HTTP请求报文,服务器接受请求并用包含这些对象的HTTP响应报文进行响应。



HTTP使用TCP作为它的运输层协议。HTTP客户机发起一个与服务器的TCP连接,一旦连接建立,浏览器和服务器进程就可以通过套接字接口访问TCP。一旦客户机发送了一个请求报文,该报文就‘脱离客户机控制’并‘进入TCP的控制’。



服务器向客户机发送被请求的文件时,并不存储任何关于该客户机的状态信息。假如某个客户机在几秒内两次请求同一对象,服务器并不会因为刚刚为该用户提供了该对象就不再做出反应,而是重新发送该对象。因为一个HTTP服务器并不保存关于客户机的任何信息,所以我们说HTTP是一个无状态协议(statelessprotocol)。



2.2.2非持久连接和持久连接



在许多因特网应用中,客户机和服务器进行长时间通信,其中客户机发出一系列请求,服务器对每个请求进行响应。根据不同的应用程序及应用程序使用的方式,这一系列请求可以周期性地一个一个发出,也可以间断性地发出。当这种客户机/服务器的交互运行于TCP协议上时,应用程序的研制者需要确定每个请求/响应对是经一个单独的TCP连接发送,还是所有的请求及相应的响应经相同的TCP连接发送。如果采用前一种方法,该应用程序被称为使用非持久连接(non-persistentconnection);如果采用后一种方法,该应用程序被称为持久连接(persistentconnection)。



在非持久连接的情况下,从服务器向客户机发送一个Web页面(含有一个基本HTML文件和10个JPEG图形)的步骤:

HTTP客户机进程在端口号80发起一个到服务器的TCP连接,该端口号是HTTP默认端口。客户机和服务器上分别有一个套接字与该连接相连。



HTTP客户机经它的套接字向服务器发送一个HTTP请求报文。



HTTP服务器进程经它的套接字接收该请求报文,从其存储器中检索出对象,在一个HTTP响应报文中封装对象,并通过套接字向客户机发送响应报文。



HTTP服务器进程通知TCP断开该TCP连接。(但直到TCP确认客户机已经完整地接收到响应报文为止,它才会真正中断连接)



HTTP客户机接收响应报文,TCP连接关闭。报文指出封装的对象时一个HTML文件,客户机从响应报文中提取出该文件,检查该文件,得到对10个JPEG图形的引用。



对每个引用的JPEG图形对象重复前4步。



从上面的例子可以看出,每个TCP连接只传输一个请求报文和一个响应报文。因此,用户请求该Web页面,要建立11个TCP连接。



当浏览器收到Web页面后,把它显示给用户。不同的浏览器可能会以不同的方式解释该页面。HTTP协议并不管客户机如何解释一个Web页面,仅定义在HTTP客户机程序与HTTP服务器程序之间的通信协议。



一个小分组从客户机到服务器再回到客户机所花费的时间称为往返时间(Round-TripTime,RTT)。RTT包括分组传播时延、分组在中间路由器和交换机上的排队时延以及分组处理时延。请求并接收一个HTML文件所需的时间大概为两个RTT(发起TCP连接和请求文件)加上服务器传输HTML文件的时间再加上客户机接收文件的时间。



非持久连接有一些缺点。首先,必须为每一个请求的对象建立和维护一个全新的连接,对于每个这样的连接,在客户机和服务器都要分配TCP的缓冲区和变量,这给服务器带来了严重的负担。其次,每一个对象的传输时延为两个RTT,即一个RTT用于建立TCP,另一个RTT用于请求和接收一个对象。



在持久连接的情况下,服务器在发送响应后保持该TCP连接打开。在相同的客户机与服务器之间的后续请求和响应报文可通过相同的连接进行传送。特别是一个完整的Web页面(如包含11个对象或更多)可以用单个持久TCP连接进行传送。而且在同一台服务器上的多个Web页面可以在单个持久TCP连接上一个接一个的发送。



如果一个连接经过一定时间间隔(一个可配置的超时间隔)仍未被使用,HTTP服务就关闭该连接。HTTP的默认模式使用了流水线方式的持久连接。



2.2.3HTTP报文格式



[RFC2616]包含了对HTTP报文格式的定义。HTTP报文有两种:请求报文和响应报文。

HTTP请求报文:



GET/somedir/page.htmlHTTP/1.1

Host:www.someschool.edu

Connection:close

User-agent:Mozilla/4.0

Accept-language:fr



仔细观察这个请求报文能知道很多信息。首先,该报文是用普通的ASCⅡ文本书写的。其次,该报文含有5行,而实际的请求报文可以有更多行或仅有一行。每行用一个回车换行符结束,最后一行后跟有附加的回车换行符。HTTP请求报文的第一行叫做请求行(requestline),其后继的行叫做首部行(headerline)。请求行有3个字段:方法字段、URL字段和HTTP协议版本字段。方法字段可以取值GET、POST、HEAD、PUT和DELETE。绝大部分的HTTP请求报文使用GET方法。URL字段填写请求对象的地址。版本字段是自解释的,本例中,是HTTP/1.1版本。



再看本例的首部行。首部行Host:www.someschool.edu定义了目标所在的主机。你或许认为该首部行是不必要的,因为在该主机中已经有一个TCP连接了。但是,后续我们将知道,该首部行提供的信息是Web代理高速缓存所要求的。Connection:close首部行,浏览器告诉服务器不希望麻烦的使用持久连接,它要求服务器在发送完被请求的对象后就关闭连接。User-agent:首部行用来定义用户代理,即向服务器发送请求的浏览器的类型。这里的浏览器类型是Mozilla/4.0,即Netscape浏览器。这个首部行是有用的,因为服务器可以正确地为不同类型的用户代理实际发送相同对象的不同版本。最后Accept-language:fr首部行表示用户想得到该对象的法语版本,否则使用服务器的默认版本。







我们再看看请求报文的通用格式。如图2-8所示。该通用格式与前面的例子密切对应。在首部行(和附加的回车换行符)后有一个‘实体主体’(entitybody)。使用GET方法时实体主体为空,而使用POST方法时才使用。例如,用户向搜索引擎提供搜索关键词,在使用POST方法的报文中,用户仍可以向服务器请求一个Web页面,但Web页面的特定内容依赖于用户输入的内容,实体主体中包含的就是用户输入的值。



HEAD方法类似于GET方法。当服务器收到使用HEAD方法的请求时,会用一个HTTP报文进行响应,但是并不返回请求对象。应用程序开发者常用HEAD方法进行故障跟踪。



PUT方法常与Web发行工具联合使用,用户利用它来将对象上传到指定的Web服务器上指定的路径。PUT方法也被应用程序用来向Web服务器上传对象。



利用DELETE方法,用户或者应用程序可以删除Web服务器上的对象。



HTTP响应报文



HTTP/1.1200OK

Connection:close

Date:Thu,03Jul200312:00:15GMT

Server:Apache/1.3.0(Unix)

Last-Modified:Sun,6May200709:23:24GMT

Content-Length:6821

Content-Type:text/html



(datadatadatadatadata…)



这个响应报文分成三个部分:一个初始状态行(statusline),6个首部行(headerline),然后是实体主体(entitybody)。实体主体部分是报文的主体,即它包含了所请求的对象本身(表示为datadatadatadatadata…)。状态行有3个字段:协议版本、状态码和相应状态信息。在此例子中,状态行指示服务器使用的协议是HTTP/1.1,并且一切正常。



我们先看首部行。服务器用Connection:close首部行告诉客户机在报文发送完后关闭了该TCP连接。Date:首部行指示服务器产生并发送该响应报文的日期和时间。值得一提的是,这个时间不是指对象创建或者最后修改的时间,而是服务器从它的文件系统中检索到该对象、插入到响应报文并发送该响应报文的时间。Server:首部行表明该报文是由一个ApacheWeb服务器产生的,它类似于HTTP请求报文中的User-agent:首部行。Last-Modifield:首部行指示了对象创建或者最后修改的日期和时间。该首部行对既可能在客户机也可能在网络缓存服务器上的对象缓存来说非常重要。Content-Length:首部行表明了被发送对象的字节数。Content-Type:首部行指示了实体主体中的对象是HTML文本。







我们再来看看响应报文的通用格式,如图2-9所示。该通用格式与前面例子中的响应报文相对应。仅补充说明一下状态码和它们对应的短语,它们指示了请求的结果。一些常见的状态码和相关的短语有:



200OK:请求成功,信息包含在返回的响应报文中。

301Movedpermanently:请求的对象已经被永久转移了,新的URL定义在响应报文的Location:首部行中指定。客户机软件自动用新的URL获取该对象。

400BadRequest:一个通用差错代码,指示该请求不能被服务器理解。

404NotFound:被请求的文档不在服务器上。

505HTTPVersionNotSupported:服务器不支持请求报文使用的HTTP协议的版本



用户与服务器的交互:cookie



HTTP服务器是无状态的。一个Web站点如果希望能够识别用户,既可能是因为服务器想限制用户的访问,有可能是因为它想把内容与用户身份关联起来。为此,HTTP使用了cookie。cookie在[RFC2109]中进行定义,它允许站点跟踪用户。



cookie技术有4个组成部分:在HTTP响应报文中有一个cookie首部行;在HTTP请求报文中有一个cookie首部行;在用户端系统中保留有一个cookie文件,由用户的浏览器管理;在Web站点有一个后端数据库。



cookie可以用于识别用户。用户首次访问站点时,可能需要提供一个用户标识。在后继访问中,浏览器向服务器传递一个cookie首部,该服务器识别该用户。因此,cookie可以在无状态的HTTP上建立一个会话层。



尽管cookie常常能简化用户与应用程序的因特网活动,但是它的作用仍有很大的争议,因为它们被看作是对用户隐私的一种侵害。就像上面说的那样,结合cookie和用户提供的账户信息,Web站点可以知道许多有关用户的信息,并可能将这些信息出卖给第三方。



Web缓存



Web缓存器(Webcache)也叫代理服务器(proxyserver),它是能够代表初始Web服务器来满足HTTP请求的网络实体。Web缓存器有自己的磁盘存储空间,并在该存储空间中保存最近请求过的对象的拷贝。可以通过配置用户的浏览器,使得用户的所有HTTP请求首先指向Web缓存器。一旦配置了浏览器,每个浏览器对一个对象的请求首先被定向到Web缓存器。例如:浏览器正在请求对象http://www.aaa.com/aaa/bbb.jpg,将会发生下列情况。



浏览器建立一个到Web缓存器的TCP连接,并向Web缓存器中的对象发送一个HTTP请求。



Web缓存器检查本地是否存储了该对象拷贝。如果有,Web缓存器就用HTTP响应了报文向客户机浏览器返回该对象。



如果Web缓存器没有该对象,它就与该对象的初始服务器打开一个TCP连接。Web缓存器则在TCP连接上发送获取该对象的HTTP请求。在收到请求后,初始服务器向Web缓存器发送具有该对象的HTTP响应。



当Web缓存器接收该对象时,它在本地存储空间存储了一份拷贝,并用HTTP响应报文向客户机的浏览器发送该拷贝。



在因特网上部署Web缓存器有两个原因。首先,Web缓存器可以大大地减少对客户机请求的响应时间,特别是当客户机与初始服务器之间的瓶颈带宽远低于客户机与Web缓存器之间的瓶颈带宽时更是如此。如果在客户机和Web缓存器之间有一个高速连接,并且用户请求的对象在Web缓存器上,则Web缓存器可以迅速将该对象交付给用户。其次,Web缓存器可以大大减少一个机构内部网与因特网接入链路上的通信量。通过减少通信量,该机构就不必急于增加带宽,因此会降低费用。此外,Web缓存器能从整体上大大降低因特网上的Web流量,从而改善了所有应用的性能。



条件GET方法



尽管高速缓存能减少用户感受到的响应时间,但也引入了一个新的问题,即存放在缓存器中的对象拷贝可能是陈旧的。换句话说,保存在服务器中的对象在该拷贝缓存在客户机后可能已经被修改了。HTTP协议有一种机制,允许缓存器证实它的对象是最新的。这种机制就是条件GET(conditionalGET)方法。如果请求报文使用GET方法;请求报文包含一个If-modified-since:首部行,那么这个HTTP请求报文就是一个条件GET请求报文。



为了描述GET方法是如何操作的,我们来看一个例子。第一,一个代理缓存器代表一个请求浏览器,向某Web服务器发送一个请求报文:



GET/fruit/kiwi.gifHTTP/1.1

Host:www.exotiquecuisine.com

第二,Web服务器向缓存器发送具有被请求的对象的响应报文:



HTTP/1.1200OK

Date:Thu,7Jul200715:39:29

Server:Apache/1.3.0(Unix)

Last-Modified:Mon,4Jul200709:23:24

Content-Type:image/gif



(datadatadatadatadata…)



缓存器在将对象转发到请求的浏览器的同时,也将对象保存在本地缓存器中。重要的是,缓存器在存储对象时也存储了最后修改时间。



第三,一个星期后,另一个用户通过该缓存器请求同一个对象,该对象仍在这个缓存器中。由于在过去的一个星期中位于Web服务器上的该对象可能已经被修改了,该缓存器通过发送一个条件GET,执行最新检查。具体来说,该缓存器发送:



GET/fruit/kiwi.gifHTTP/1.1

Host:www.exotiquecuisine.com

If-modified-since:Wed,4Jul200709:23:24



注意到If-modified-since:首部行的值正好等于一星期前服务器发送的响应报文中的Last-Modified:首部行的值。该条件GET报文告诉服务器,仅当自指定日期之后修改过该对象才发送该对象。假设该对象自4Jul200709:23:24后没有被修改。接下来,第四步,Web服务器向该缓存器发送一个响应报文:



HTTP/1.1304NotModified

Date:Sat,14Jul200715:39:29

Server:Apache/1.3.0(Unix)



(实体主体为空)



我们看到,作为对该条件GET方法的响应,Web服务器发送一个响应报文,但并没有包含所请求的对象。包含该对象只是对带宽的浪费,并增加用户感受到的响应时间,特别是当该对象很大的时候。应当注意在最后的响应报文中,状态行中状态码和相应状态信息的值为304NotModified,它告诉缓存器可以使用该对象,向请求的浏览器转发该对象的拷贝。

献花(0)
+1
(本文系miracle859首藏)