一、HTTP概况


 

  20世纪90年代初期,一个主要的新兴应用即万维网(World Wide Web)登上了舞台。Web是一个引起公众注意的因特网应用。Web的应用层协议是超文本传输协议(HTTP),它是Web的核心。HTTP由两个程序实现:一个客户程序和一个服务器程序。客户程序和服务器程序运行在不同的端系统中,通过交换HTTP报文进行会话。HTTP会话定义了这些报文的结构以及客户和服务器进行报文交换的方式。

  Web页面(也叫文档)是由对象组成的。一个对象只是一个文件,诸如一个HTML文件、一个JPEG图形、一个Java小程序或一个视频片段这样的文件,且他们可通过一个URL地址寻址。多数Web页面含有一个HTML基本文件以及几个引用对象。例如,如果一个Web页面包含HTML基本文件和5个JPEG图形,那么这个Web页面6个对象:一个HTML基本文件加5个图形。HTML基本文件通过对象的URL地址引用页面中的其他对象。每个URL地址由两部分组成:存放对象的服务器主机名和对象的路径名。Web浏览器实现了HTTP的客户端,Web服务器实现了HTTP的服务器端,它用于存储Web对象,每个对象由URL寻址。

  HTTP定义了Web客户向Web服务器请求Web页面的方式,以及服务器向客户传送Web页面的方式,其基本思想就是当用户请求一个Web页面(如点击一个超链接)时,浏览器向服务器发出对该页面中所包含对象的HTTP请求报文,服务器接收到请求并用包含这些对象的HTTP响应报文进行响应。

  HTTP使用TCP作为它的支撑运输协议(而不是在UDP上运行)。HTTP客户首先发起一个与服务器的TCP连接。一旦连接建立,该浏览器和服务器进程就可以通过套接字接口访问TCP。客户向它的套接字接口发送HTTP请求报文并从它的套接字接口接收HTTP响应报文。类似的,服务器从它的套接字接口接收HTTP请求报文和向它的套接字接口发送HTTP响应报文。一旦客户向他的套接字接口发送了一个请求报文,该报文就脱离了客户控制并进入TCP的控制。TCP为HTTP提供可靠数据传输服务。这意味着,一个客户进程发出的每个HTTP请求报文最终能完整地到达服务器;类似的,服务器进程发出的每个HTTP响应报文最终能完整地到达客户。

  注意到下列现象很重要:服务器向客户发送被请求的文件,而不存储任何关于该客户的状态信息。假如某个特定的客户在短短的几秒钟内两次请求同一个对象,服务器并不会因为刚刚为该客户提供了该对象就不再做出反应,而是重新发送该对象,就像服务器已经完全忘记不久之前所做过的事一样。因为HTTP服务器并不保存关于客户的任何信息,所以我们说HTTP是一个无状态协议


 

二、非持续连接和持续连接


 

  在许多因特网应用程序中,客户和服务器在一个相当长的时间范围内通信,其中客户发出一系列请求并且服务器对每个请求进行响应。依据应用程序以及该应用程序的使用方式,这一系列请求可以以规则的间隔周期性的或者间断性的一个接一个发出。当这种客户-服务器的交互是经TCP进行的,应用程序的研制者就要做一个重要决定,即每个请求/响应对是经一个单独的TCP连接发送,还是所有的请求及其相应经相同的TCP连接发送呢?采用前一种方法,该应用程序被称为使用非持续连接;采用后一种方法,该应用程序被称为使用持续连接。如HTTP既能够使用非持续连接,也能够使用持续连接。尽管HTTP在默认方式下使用持续连接,HTTP客户和服务器也能配置成非持续连接。

1.采用非持续连接的HTTP

  我们看看在非持续连接情况下,从服务器向客户传送一个Web页面的步骤。假设该页面含有一个HTML基本文件和10个JPEG图形,并且这11个对象位于同一台服务器上。该HTML文件的URL为:http://www.someSchool.edu/someDepartment/home.index我们看看发生了什么情况:

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

  • HTTP客户经它的套接字向该服务器发送一个HTTP请求报文。请求报文中包含了路径名/someDepartment/home.index。

  • HTTP服务器进程经它的套接字接收该请求报文,从其存储器(RAM或磁盘)中检索出对象http://www.someSchool.edu/someDepartment/home.index,在一个HTTP响应报文中封装对象,并通过其套接字向客户发送响应报文。

  • HTTP服务器进程通知TCP断开该TCP连接。(但是直到TCP确认客户已经完整的收到响应报文为止,它才会实际中断连接。

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

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

  上面的步骤举例说明了非持续连接的使用,其中每个TCP连接在服务器发送一个对象后关闭,即该连接并不为其他的对象而持续下来。值得注意的是每个TCP来接只传输一个请求报文和响应报文。

     在上面描述的步骤中,我们有意没有明确客户获得这10个JPEG图形对象是使用10个串行的TCP连接,还是某些JPEG对象使用了一些并行的TCP连接。事实上,用户能配置现代浏览器以控制并行度。在默认方式下,大部分浏览器打开5~10个并行的TCP连接,而每条连接处理一个请求响应事务。如果用户愿意,最大并行连接数可以设置为1,这样10条连接就会串行建立。

  我们来简单估算一下从客户请求HTML基本文件起到该客户收到整个文件止所花费的时间。为此,我们给出往返时间(Round-Trip Time,RTT)的定义,该时间是指一个短分组从客户到服务器然后再返回客户所花费的时间。RTT包括分组传播时延、分组在中间路由器和交换机上的排队时延以及分组处理时延。现在考虑当用户点击超链接时会发生什么现象。如图2-7所示,这引起浏览器在它和Web服务器之间发起一个TCP连接;这涉及一次“三次握手”过程。即客户向服务器发送一个小TCP报文段,服务器用一个小TCP报文段做出确认和响应,最后,客户向服务器返回确认。三次握手中前两个部分所耗费的时间占用了一个RTT。完成了三次握手的前两个部分后,客户结合三次握手的第三部分(确认)向该TCP连接发送一个HTTP请求报文。一旦该请求报文到达服务器,服务器就在该TCP连接上发送HTML文件。该HTTP请求/响应用去了另一个RTT。因此,粗略地将,总的响应时间就是两个RTT加上服务器传输HTML文件的时间。

2.采用持续连接的HTTP

  非持续连接有一些缺点。首先,必须为每一个请求的对象建立和维护一个全新的连接。对于每个这样的连接,在客户和服务器中都要分配TCP的缓冲区和保持TCP变量,这给Web服务器带来了严重的负担,因为一台Web服务器可能同时服务于数以百计不同的客户的请求。第二,就像我们刚描述的那样,每一个对象经受两倍RTT的交付时延,即一个RTT用于创建TCP,另一个RTT用于请求和接收一个对象。

  在采用持续连接的情况下,服务器在发送响应后保持该TCP连接打开。在相同的客户与服务器之间的后续请求和响应报文能够通过相同的连接进行传送。特别是,一个完整的Web页面(上例中的HTML基本文件加上10个图形)可以用单个持续TCP连接进行传送。更有甚者,位于同一台服务器的多个Web页面在从该服务器发送给同一个客户时,可以在单个持续TCP连接上进行。可以一个接一个地发出对对象的这些请求,而不必等待对未决请求(流水线)的回答。一般来说,如果一条连接经过一定的时间间隔(一个可配置的超时间隔)仍未被使用,HTTP服务器就关闭该连接。HTTP的默认模式是使用带流水线的持续连接。


三、HTTP报文格式

  HTTP报文有两种:请求报文和响应报文。

1.HTTP请求报文

  下面提供了一个典型的HTTP请求报文:

GET /somedir/page.html HTTP/1.1

Host: www.someschool.edu

Connection: close

User-agent: Mozilla/5.0

Accept-language: fr

  通过仔细观察这个简单的请求报文,我们就能知道很多东西。首先,我们看到该报文是用普通的ASCII文本书写的,我们看到该报文由5行组成,每行由一个回车和换行符结束。最后一行后再附加一个回车换行符。一个请求报文能够具有更多的行或者至少为一行。请求行的方法字段可以取几种不同的值,包括GET、POST、HEAD、PUT和DELETE。当浏览器请求一个对象时,使用GET方法,在URL字段带有请求对象的标识,在本例中,该浏览器正在请求对象/somedir/page.html。其版本字段是自解释的;在本例中,浏览器实现的是HTTP/1.1版本。现在我们看看本例的首部行。首部行Host: www.someschool.edu指明了对象所在的主机。你也许认为该首部行是不必要的,因为在该主机中已经有一条TCP连接存在了,但是,该首部行提供的信息是Web代理高速缓存所要求的。通过包含Connection: close首部行,该浏览器告诉服务器不希望麻烦地使用持续连接,它要求服务器在发送完被请求的对象后就关闭这条连接。User-agent: 首部行用来指明用户代理,即向服务器发送请求的浏览器类型。这里浏览器类型是Mozilla/5.0,即Firefox浏览器。这个首部行是有用的,因为服务器可以有效地为不同类型的用户代理实际发送相同对象的不同版本。(每个版本都由相同的URL寻址。)最后,Accept-language: 首部行表示用户想得到该对象的法语版本。如果服务器中没有这样的对象的话,服务器应当发送它的默认版本。

  接下来看看如图2-8所示的一个请求报文的通用格式。你可能注意到了在首部行(和附加的回车和换行)后有一个“实体主体”。使用GET方法是实体主体为空,而使用POST方法时才使用该实体主体。当用户提交表单时,HTTP客户常常使用POST方法,例如当用户向搜索引擎提供搜索关键词时。使用POST报文时,用户仍可以向服务器请求一个Web页面,但Web页面的特定内容依赖于用户在表单字段中输入的内容。如果方法字段的值为POST时,则实体主体中包含的就是用户在表单字段中的输入值。

  当然,如果不提“用表单生成的请求报文不是必须使用POST方法”这一点,那将是失职。HTML表单经常使用GET方法,并在(表单字段中)所请求的URL中包括输入的数据。例如,一个表单使用GET方法,它有两个字段,分别填写的是“monkeys”和“bananas”,这样,该URL结构为www.somesite.com/animalsearch? monkeys&bananas。

  HEAD方法类似GET方法。当服务器收到使用HEAD方法的请求时,将会用一个HTTP报文进行响应,但是并不返回请求对象。应用程序开发者常用HEAD方法进行调试跟踪。PUT方法常与Web发行工具联合使用,它允许用户上传对象到指定的Web服务器上指定的路径(目录)。PUT也被那些需要向Web服务器上传对象的应用程序使用。DELETE方法允许用户或者应用程序删除Web服务器上的对象。

2.HTTP响应报文

  下面我们提供了一条典型的HTTP响应报文。该响应报文可以是对刚刚讨论的例子中请求报文的响应。

HTTP/1.1 200 OK

Connection: close

Date: Tue, 09 Aug 2011 15:44:04 GMT

Server: Apache/2.2.3 (CentOS)

Last-Modified: Tue, 09 Aug 2011 15:11:03 GMT

Content-Length: 6821

Content-Type: text/html

(data data data data data …)

  我们仔细看这个响应报文。实体主体部分是报文的主要部分,即它包含了所请求的对象本身(表示为data data data data data …)。我们现在来看看首部行。服务器用Connection:close首部行告诉客户,发送完报文后将关闭该TCP连接。Date:首部行指示服务器产生并发送该响应报文的日期和时间。值得一提的是,这个时间不是指对象创建或者最后修改的时间;而是服务器从它的文件系统中检索到该对象,插入到响应报文,并发送响应报文的时间。Server:首部行指示该报文是由一台Apache Web服务器产生的,它类似于HTTP请求报文中的User-agent:首部行,Last-Modified:首部行指示了对象创建或者最后修改的日期和时间。Last-Modified:首部行对极可能在本地客户也可能在网络缓存服务器(代理服务器)上的对象缓存来说非常重要。Content-Length:首部行知识了被发送对象中的字节数。Content-Type:首部行指示了实体主体中的对象是HTML文本。(该对象类型应该正式地由Content-Type:首部行而不是用文件扩展名来指示。)

  看过一个例子后,我们再来查看响应报文的通用格式(如图2-9所示)。我们补充说明一下状态码和它们对应的短语。状态码及其相应的短语指示了请求的结果。一些常见的状态码和相关的短语包括:

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

  • 301 Moved Permanently:请求的对象已经被永久转移了,新的URL定义在响应报文的Location:首部行中。**客户软件将自动获取新的URL。

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

  • 404 Not Found:被请求的文档不在服务器上。

  • 505 HTTP Version Not Supported:服务器不支持请求报文使用的HTTP协议版本。

  你想看一下真正的HTTP响应报文吗?很容易做到。首先用Telnet登录到你喜欢的Web服务器上,接下来输入一个只有一行的请求报文去请求放在该服务器上的某些对象。

  在linux终端输入完telnet www.baidu.com 80后,会是下面这种情况:

  然后按下ctrl + ]呼出telnet命令行出现下面这种情况:

  先按下回车键,再输入HTTP请求,最终得到HTTP响应如下:

  在telnet命令行上输入quit退出telnet,如下图:

 


 

 

版权声明:本文为Gland原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Gland/p/HTTP.html