团购网站做摄影,广州番禺区天气预报15天,微分销登录,建导航网站轻松认识HTTP协议的概念和工作原理 当我们想浏览一个网站的时候#xff0c;只要在浏览器的地址栏里输入网站的地址就可以了#xff0c;例如#xff1a;www.microsoft.com#xff0c;但是在浏览器的地址栏里面出现的却是#xff1a;http://www.microsoft.com#xff0c;你…轻松认识HTTP协议的概念和工作原理 当我们想浏览一个网站的时候只要在浏览器的地址栏里输入网站的地址就可以了例如www.microsoft.com但是在浏览器的地址栏里面出现的却是http://www.microsoft.com你知道为什么会多出一个“http”吗一、HTTP协议是什么我们在浏览器的地址栏里输入的网站地址叫做URL(UniformResourceLocator统一资源定位符)。就像每家每户都有一个门牌地址一样每个网页也都有一个Internet地址。当你在浏览器的地址框中输入一个URL或是单击一个超级链接时URL就确定了要浏览的地址。浏览器通过超文本传输协议(HTTP)将Web服务器上站点的网页代码提取出来并翻译成漂亮的网页。因此在我们认识HTTP之前有必要先弄清楚URL的组成,例如http://www.microsoft.com/china/index.htm。它的含义如下1.http://代表超文本传输协议通知microsoft.com服务器显示Web页通常不用输入2.www代表一个Web(万维网)服务器3.Microsoft.com/这是装有网页的服务器的域名或站点服务器的名称4.China/为该服务器上的子目录就好像我们的文件夹5.Index.htmindex.htm是文件夹中的一个HTML文件(网页)。我们知道Internet的基本协议是TCP/IP协议然而在TCP/IP模型最上层的是应用层(Applicationlayer)它包含所有高层的协议。高层协议有文件传输协议FTP、电子邮件传输协议SMTP、域名系统服务DNS、网络新闻传输协议NNTP和HTTP协议等。HTTP协议(HypertextTransferProtocol超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效使网络传输减少。它不仅保证计算机正确快速地传输超文本文档还确定传输文档中的哪一部分以及哪部分内容首先显示(如文本先于图形)等。这就是你为什么在浏览器中看到的网页地址都是以“http://”开头的原因。自WWW诞生以来一个多姿多彩的资讯和虚拟的世界便出现在我们眼前可是我们怎么能够更加容易地找到我们需要的资讯呢当决定使用超文本作为WWW文档的标准格式后于是在1990年科学家们立即制定了能够快速查找这些超文本文档的协议即HTTP协议。经过几年的使用与发展得到不断的完善和扩展目前在WWW中使用的是HTTP/1.0的第六版。二、HTTP是怎样工作的既然我们明白了URL的构成那么HTTP是怎么工作呢我们接下来就要讨论这个问题。由于HTTP协议是基于请求/响应范式的(相当于客户机/服务器)。一个客户机与服务器建立连接后发送一个请求给服务器请求方式的格式为统一资源标识符(URL)、协议版本号后边是MIME信息包括请求修饰符、客户机信息和可能的内容。服务器接到请求后给予相应的响应信息其格式为一个状态行包括信息的协议版本号、一个成功或错误的代码后边是MIME信息包括服务器信息、实体信息和可能的内容。许多HTTP通讯是由一个用户代理初始化的并且包括一个申请在源服务器上资源的请求。最简单的情况可能是在用户代理和服务器之间通过一个单独的连接来完成。在Internet上HTTP通讯通常发生在TCP/IP连接之上。缺省端口是TCP80但其它的端口也是可用的。但这并不预示着HTTP协议在Internet或其它网络的其它协议之上才能完成。HTTP只预示着一个可靠的传输。这个过程就好像我们打电话订货一样我们可以打电话给商家告诉他我们需要什么规格的商品然后商家再告诉我们什么商品有货什么商品缺货。这些我们是通过电话线用电话联系(HTTP是通过TCP/IP)当然我们也可以通过传真只要商家那边也有传真。以上简要介绍了HTTP协议的宏观运作方式下面介绍一下HTTP协议的内部操作过程。在WWW中“客户”与“服务器”是一个相对的概念只存在于一个特定的连接期间即在某个连接中的客户在另一个连接中可能作为服务器。基于HTTP协议的客户/服务器模式的信息交换过程它分四个过程建立连接、发送请求信息、发送响应信息、关闭连接。这就好像上面的例子我们电话订货的全过程。其实简单说就是任何服务器除了包括HTML文件以外还有一个HTTP驻留程序用于响应用户请求。你的浏览器是HTTP客户向服务器发送请求当浏览器中输入了一个开始文件或点击了一个超级链接时浏览器就向服务器发送了HTTP请求此请求被送往由IP地址指定的URL。驻留程序接收到请求在进行必要的操作后回送所要求的文件。在这一过程中在网络上发送和接收的数据已经被分成一个或多个数据包(packet)每个数据包包括要传送的数据控制信息即告诉网络怎样处理数据包。TCP/IP决定了每个数据包的格式。如果事先不告诉你你可能不会知道信息被分成用于传输和再重新组合起来的许多小块。也就是说商家除了拥有商品之外它也有一个职员在接听你的电话当你打电话的时候你的声音转换成各种复杂的数据通过电话线传输到对方的电话机对方的电话机又把各种复杂的数据转换成声音使得对方商家的职员能够明白你的请求。这个过程你不需要明白声音是怎么转换成复杂的数据的。 了解WWW服务与HTTP协议 在前一篇文章里我们介绍了网络应用和网络协议的一些基础知识现在让我们来了解一下WWW服务应用和HTTP网络协议。 历史上先后问世了多个具有重大社会影响的电子通信技术。第一个这样的技术是19世纪70年代发明的电话。电话使得不在同一物理位置的两人得以实时地口头交流。它对社会有重大的影响——有好的也有坏的。下一个电子通信技术是20世纪20年代及30年代问世的广播收音机/电视机。广播收音机/电视机使得人们能收听收视大量的音频和视频信息。它对社会同样有重大的影响——有好的也有坏的。改变了人们的生活与工作方式的第三个重大通信技术是web。web最吸引用户的也许是它的随选(on demand)操作性。用户只在想要时收到所要的东西。这一点不同于广播收音机/电视机。广播收音机/电视机的用户是在其内容供应商播出内容期间被迫收听收视。除了随选操作性Web还有许多大家喜爱的其他精彩特性。任何个人都可以极其容易地在Web上公布任何信息;任何人都可能以极低的成本成为发行人。超链接和搜索引擎帮助我们在Web站点的海洋中导航。图形和动画刺激着我们的感官。表单、Java小应用程序、Activex控件以及其他许多设备使得我们能与Web页面和站点交互。Web还越来越普遍地提供存放在因特网中的、可随选访问(即点播)的大量音频和视频材料的菜单接口。 HTTP概貌 Web的应用层协议HTTP是Web的核心。HTTP在Web的客户程序和服务器程序中得以实现。运行在不同端系统上的客户程序和服务器程序通过交换HTTP消息彼此交流。HTTP定义这些消息的结构以及客户和服务器如何交换这些消息。在详细解释HTTP之前我们先来回顾一些web中的术语。 Web页面(web page也称为文档)由多个对象构成。对象(object)仅仅是可由单个URL寻址的文件例如HTML文件、JPG图像、GIF图像、JAVA小应用程序、语音片段等。大多数Web页面由单个基本HIML文件和若干个所引用的对象构成。例如如果一个Web页面包含HTML文本和5个JPEG图像那么它由6个对象构成即基本H1ML文件加5个图像。基本HTML文件使用相应的URL来引用本页面的其他对象。每个URL由存放该对象的服务器主机名和该对象的路径名两部分构成。例如在如下的URL中: www.chinaitlab.com/urlpath/picture.qif www.chinaitlab.com是一个主机名/urlpath/picture.qif是一个路径名。浏览器是web的用户代理它显示所请求的Web页面并提供大量的导航与配置特性。Web浏览器还实现HTTP的客户端因此在web上下文中我们会从进程意义上互换使用“浏览器”和“客户”两词。流行的Web浏览器有Netscape Communicatorfirefox和微软的IE等。Web服务器存放可由URL寻址的Web对象。web服务器还实现HTTP的服务器端。流行的Web服务器有Apache、微软的IIS以及Netscape Enterprise Server。Netcraft提供了web服务器的概要剖析[Netcrft 2000]。 HTTP定义Web客户(即浏览器)如何从web服务器请求Web页面以及服务器如何把Web页面传送给客户。下图展示了这种请求—响应行为。当用户请求一个Web页面(譬如说点击某个超链接)时浏览器把请求该页面中各个对象的HTTP请求消息发送给服务器。服务器收到请求后以运送含有这些对象HTTP响应消息作为响应。到1997年底基本上所有的浏览器和Web服务器软件都实现了在RFC 1945中定义的HTTP/1.0版本。1998年初一些Web服务器软件和浏览器软件开始实现在RFC 2616中定义的HTTP/1.1版本。H1TP/1.1与HTTP/1.0后向兼容;运行1.1版本的web服务器可以与运行1.0版本的浏览器“对话”运行1.1版本的浏览器也可以与运行1.0版本的Web服务器“对话”。 图1 HTTP请求与响应行为 HTTP/1.0和HTTP/1.1都把TCP作为底层的传输协议。HTTP客户首先发起建立与服务器TCP连接。一旦建立连接浏览器进程和服务器进程就可以通过各自的套接字来访问TCP。如前所述客户端套接字是客户进程和TCP连接之间的“门”服务器端套接字是服务器进程和同一TCP连接之间的“门”。客户往自己的套接字发送HTTP请求消息也从自己的套接字接收HTTP响应消息。类似地服务器从自己的套接字接收HTTP请求消息也往自己的套接字发送HTTP响应消息。客户或服务器一旦把某个消息送入各自的套接字这个消息就完全落入TCP的控制之中。TCP给HTTP提供一个可靠的数据传输服务;这意味着由客户发出的每个HTTP请求消息最终将无损地到达服务器由服务器发出的每个HTTP响应消息最终也将无损地到达客户。我们可从中看到分层网络体系结构的一个明显优势——HTTP不必担心数据会丢失也无需关心TCP如何从数据的丢失和错序中恢复出来的细节。这些是TCP和协议栈中更低协议层的任务。 TCP还使用一个拥塞控制机制。该机制迫使每个新的TCP连接一开始以相对缓慢的速率传输数据然而只要网络不拥塞每个连接可以迅速上升到相对较高的速率。这个慢速传输的初始阶段称为缓启动(slow start)。 需要注意的是在向客户发送所请求文件的同时服务器并没有存储关于该客户的任何状态信息。即便某个客户在几秒钟内再次请求同一个对象服务器也不会响应说:自己刚刚给它发送了这个对象。相反服务器重新发送这个对象因为它已经彻底忘记早先做过什么。既然HTTP服务器不维护客户的状态信息我们于是说HTTP是一个无状态的协议(stateless protocol)。 非持久连接和持久连接 HTTP既可以使用非持久连接(nonpersistent connection)也可以使用持久连接(persistent connection)。HTTP/1.0使用非持久连接HTTP/1.1默认使用持久连接。 非持久连接 让我们查看一下非持久连接情况下从服务器到客户传送一个Web页面的步骤。假设该贝面由1个基本HTML文件和10个JPEG图像构成而且所有这些对象都存放在同一台服务器主机中。 再假设该基本HTML文件的URL为:www.chinaitlab.com/somepath/index.html。 下面是具体步骡: 1.HTTP客户初始化一个与服务器主机www.chinaitlab.com中的HTTP服务器的TCP连接。HTTP服务器使用默认端口号80监听来自HTTP客户的连接建立请求。 2.HTTP客户经由与TCP连接相关联的本地套接字发出—个HTTP请求消息。这个消息中包含路径名/somepath/index.html。 3.HTTP服务器经由与TCP连接相关联的本地套接字接收这个请求消息再从服务器主机的内存或硬盘中取出对象/somepath/index.html经由同一个套接字发出包含该对象的响应消息。 4.HTTP服务器告知TCP关闭这个TCP连接(不过TCP要到客户收到刚才这个响应消息之后才会真正终止这个连接)。 5.HTTP客户经由同一个套接字接收这个响应消息。TCP连接随后终止。该消息标明所封装的对象是一个HTML文件。客户从中取出这个文件加以分析后发现其中有10个JPEG对象的引用。 6.给每一个引用到的JPEG对象重复步骡1-4。 浏览器在接收web页面的同时把它显示给用户。不同的浏览器可能会以略有不同的方式解释(也就是向用户显示)同一个web页面。HTTP与客户如何解释Web页面没有任何关系其规范([RFC 1945]和[RFC 2616I)仅仅定义HTTP客户程序和服务器程序之间的通信协议。 上述步骤之所以称为使用非持久连接原因是每次服务器发出一个对象后相应的TCP连接就被关闭也就是说每个连接都没有持续到可用于传送其他对象。每个TCP连接只用于传输一个请求消息和一个响应消息。就上述例子而言用户每请求一次那个web页面就产生11个TCP连接。 在上述步骡中我们有意不说清客户是通过10个串行的TCP连接先后取得所有JPEG对象还是通过并行的TCP连接同时取得其中某些JPEG对象。实际上现今的浏览器允许用户通过配置来控制并行连接的程度。大多数浏览器默认可以打开5到10个并行的TCP连接每个连接处理一个请求—响应事务。用户要是喜欢可以把最大并行连接数设为l那样的话这10个连接是串行地建立的。我们将在第3章看到使用并行连接可以缩短响应时间。 继续介绍之前先估算一下从客户请求基本HTML文件到它收到该文件所经历的时间。为此我们定义往返时间(round trip time简称RTT)它是一个小分组从客户主机游动到服务器主机再返回客户主机所花的时间。RTT包括分组传播延迟、在中间路由器和交换机土的分组排队延迟以及分组处理延迟。下面考虑用户点击某个超链接时会发生什么。用户的点击导致浏览器发起建立一个与Web服务器的TCP连接;这里涉及·—次“三次握手”过程——首先是客户向服务器发送一个小的冗余消息接着是服务器向客户确认并响应以一个小的TCP消息最后是客户向服务器回确认。三次握手过程的前两次结束时流逝的时间为1个RTT。此时客户把HTTP请求消息发送到TCP连接中客户接着把三次握手过程最后一次中的确认捎带在包含这个消息的数据分节中发送以去。服务器收到来自TCP连接的请求消息后把相应的HTML文件发送到TCP连接中服务器接着把对早先收到的客户请求的确认捎带在包含该HTML文件的数据分节中发送出去。这个HTTP请求顺应交互也花去1个RTT时间。因此总的响应时间粗略地算是2个RTT加上服务器发送这个HTMI文件的时间。 持久连接 非持久连接有些缺点。首先客户得为每个待请求的对象建立并维护一个新的连接。对于每个这样的连接TCP得在客户端和服务器端分配TCP缓冲区并维持TCP变量。对于有可能同时为来自数百个不同客户的请求提供服务的web服务器来说这会严重增加其负担。其次如前所述每个对象都有2个RTT的响应延长——一个RTT用于建立TCP连接另—个RTT用于请求和接收对象。最后每个对象都遭受TCP缓启动因为每个TCP连接都起始于缓启动阶段。不过并行TCP连接的使用能够部分减轻RTT延迟和缓启动延迟的影响。 在持久连接情况下服务器在发出响应后让TCP连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。整个Web页面(上例中为包含一个基本HTMLL文件和10个图像的页面)自不用说可以通过单个持久TCP连接发送:甚至存放在同一个服务器中的多个web页面也可以通过单个持久TCP连接发送。通常HTTP服务器在某个连接闲置一段特定时间后关闭它而这段时间通常是可以配置的。持久连接分为不带流水线(without pipelining)和带流水线(with pipelining)两个版本。如果是不带流水线的版本那么客户只在收到前一个请求的响应后才发出新的请求。这种情况下web页面所引用的每个对象(上例中的10个图像)都经历1个RTT的延迟用于请求和接收该对象。与非持久连接2个RTT的延迟相比不带流水线的持久连接已有所改善不过带流水线的持久连接还能进一步降低响应延迟。不带流水线版本的另一个缺点是服务器送出一个对象后开始等待下一个请求而这个新请求却不能马上到达。这段时间服务器资源便闲置了。 HTTP/1.1的默认模式使用带流水线的持久连接。这种情况下HTTP客户每碰到一个引用就立即发出一个请求因而HTTP客户可以一个接一个紧挨着发出各个引用对象的请求。服务器收到这些请求后也可以一个接一个紧挨着发出各个对象。如果所有的请求和响应都是紧挨着发送的那么所有引用到的对象一共只经历1个RTT的延迟(而不是像不带流水线的版本那样每个引用到的对象都各有1个RTT的延迟)。另外带流水线的持久连接中服务器空等请求的时间比较少。与非持久连接相比持久连接(不论是否带流水线)除降低了1个RTT的响应延迟外缓启动延迟也比较小。其原因在于既然各个对象使用同一个TCP连接服务器发出第一个对象后就不必再以一开始的缓慢速率发送后续对象。相反服务器可以按照第一个对象发送完毕时的速率开始发送下一个对象。 HTTP消息格式 HTTP规范1.0[RPcl945]和1.1[RFC 2616]定义了HTTP消息的格式。HTTP消息分为请求消息和响应稍息两类。下面我们分别进行介绍。 HTTP请求消息 下面是一个典型的HTTP请求消息: GET /somedir/page.html H7TP/1.1 Host:www.chinaitlab.com Connection:close User-agent:Mozilla/4.0 Accept-language:zh-cn (额外的回车符和换行符) 仔细检查这个简单的请求消息我们可从中学到不少东西。首先这个消息是用普通的ASCII文本书写的。其次这个消息共有5行(每行以一个回车符和一个换行符结束)最后一行后面还有额外的一个回车特和换行符。当然一个请求消息可以不止这么多行也可以仅仅只有一行。该请求消息的第一行称为请求行(request line)后续各行都称为头部行(header)。请求行有3个宁段:方法字段、URL字段、HTTP版本宇段。方法字段有若干个值可供选择包括GET、POST和HEAD。HTTP请求消息绝大多数使用GET方法这是浏览器用来请求对象的方法所请求的对象就在URL字段中标识。本例表明浏览器在请求对象/somedir/page.html。版本字段是不言自明的;本例中浏览器实现的是HTTP/1.1版本。 现在看一下本例中的各个头部行。头部行Host:www.chinaitlab.com定存放所请求对象的主机。请求消息中包含头部Connection:close是在告知服务器本浏览器不想使用持久连接;服务器发出所请求的对象后应关闭连接。尽管产生这个请求消息的浏览器实现的是HTTP/1.1版本它还是不想使用持久连接。User-agent头部行指定用户代理也就是产生当前请求的浏览器的类型。本例的用户代理是Mozilla/4.0它是Nelscape浏览器的一个版本。这个头部行很有用因为服务器实际上可以给不同类型的用户代理发送同一个对象的不同版本(这些不同版本位用同一个URL寻址)。最后Accept-languag:头部行指出要是所请求对象有简体中文版本那么用户宁愿接收这个版本;如果没有这个语言版本那么服务器应该发送其默认版本。Accept-languag:仅仅是HTTP的众多内容协商头部之一。 我们接着看一下下图所示的请求消息的一般格式。 图2:HTTP请求格式 上面的请求消息例子符合这个格式不过一般格式中还有一个位于各个头部(及额外的回车符和换行符)之后的“附属体”(毗叮body)。附属体不在GET方法中使用而是在POST方法中使用。POST方法适用于需由用户填写表单的场合如往google搜索引擎中填入待搜索的词。用户提交表单后浏览器就像用户点击了超链接那样仍然从服务器请求一个Web页面不过该页面的具体内容却取决于用户填写在表单各个字段中的值。如果浏览器使用POST方法提出该请求那么请求消息附属体中包含的是用户填写在表单各个字段中的值。与GET方法类似的是HEAD方法两者的差别只是服务器在对HEAD方法的响应消息中去掉了所请求的对象其他内容则与对GET方法的响应消息一样。HEAD方法通常用于HTTP服务器软件开发人员进行调试。 HTTP响应消息 下面是一个典型的HTTP响应消息: HTTP/1.1 200 0K Connectlon:close Date: Thu, 13 Oct 2005 03:17:33 GMT Server: Apache/2.0.54 (Unix) Last—Nodified:Mon,22 Jun 1998 09;23;24 GMT Content—Length:682l Content—Type:text/html (数据 数据 数据 数据 数据…………) 这个响应消息分为3部分1个起始的状态行(status line)6个头部行、1个包含所请求对象本身的附属体。状态行有3个字段:协议版本字段、状态码字段、原因短语字段。本例的状态行表明服务器使用HTTP/1.1版本响应过程完全正常(也就是说服务器找到了所请求的对象并正在发送)。 现在看一下本例中的各个头部行。服务器使用Connectlon:close头部行告知客户自己将在发送完本消息后关闭TCP连接。Date:头部行指出服务器创建并发送本响应消息的日期和时间。注意这并不是对象本身的创建时间或最后修改时间而是服务器把该对象从其文件系统中取出插入响应消息中发送出去的时间。Server:头部行指出本消息是由Apache服务器产生的;它与HTTP请求消息中的User-agent:头部行类似。Last—Nodified:头部行指出对象本身的创建或最后修改日期或时间。Last—Nodified:头部对于对象的高速缓存至关重要且不论这种高速缓存是发生在本地客户主机上还是发生在网络高速缓存服务器主机(也就是代理服务器主机)上。Content—Length:头部行指出所发送对象的字节数。Content—Type:头部行指出包含在附属体中的对象是HTML文本。对象的类型是由Content—Type:头部而不是由文件扩展名正式指出的。 注意如果服务器收到一个HTTP/1.0的请求那么它即使是一个HTTP/1.1服务器也不会使用持久连接。相反这样的HTTP/1.1服务器会在发出所请求的对象后关闭TCP连接。这么做是必要的因为HTTP/1.0客户期待服务器马上关闭连接。 我们接着看一下如下图所示的响应消息的一般格式。前面的响应消息例子完全符合这个格式。响应消息中的状态码和原因短语指示相应请求的处理结果下面列出了一些常见的状态码和相应的原因短语: 图3:响应消息的一般格式 ●200 0K;请求成功所请求信息在响应消息中返回。 ●301 Moved Permanently:所请求的对象己永久性迁移;新的URL在本响应消息的Location:头部指出。客户软件会自动请求这个新的URL。 ●400 Bad Request;表示服务器无法理解相应请求的普通错误的状态码 ●404 Not Found:服务器上不存在所请求的文档。 ●HTTP Version Not Support:服务器不支持所请求的HTTP协议版本。 你想如何看到一个真实的H1TP应答消息呢?这非常简单。可以使用nc工具连接到你喜欢的服务器(nc/netcat是一个黑客很喜欢用的工具可以方便在主机之间建立TCP连接)然后输入一行请求消息用来请求位于该服务器上的某个对象。例如如果你可以输入以下指令: nc www.chinaitlab.com 80 GET /index.shtml HTTP/1.0 (在输入第二行之后敲两次回车)这就打开了一个到主机www.chinaitlab.com的端口80的TCP连接然后发送HTTP GET命令。你应该能看到包含着YESKY主页的基本HTML文件的应苔消息。如果你想只看到HTTP消息行而不接收该对象本身那么就把上面的GET换成HEAD。最后看一下能得到什么样的应答消息。 在这里我们讨论了大量能够在HTTP请求和应答消息中使用的头部行。HTTP规范(尤其是HTTP/1.1)定义了更多可以由浏览器、Web服务器和网络缓冲服务器插入的头部行。 我们可以便用nc工具完全控制在请求消息中包含哪些头部那么浏览器如何决定该在请求消息个包含哪些头部呢?Web服务器又是如何决定该在响应消息中包含哪些头部?浏览器是根据自己的用户代理类型、所支持的HTTP版本(HTTP/1.0版本的浏览器自然不会产生HTTP/1.1版本的头部)、用户对浏览器的配置(如所偏爱的语言)等因素生成请求消息中的各个头部的。web服务器有类似的情形:它们有不同的产品、版本和配置所有这些因素都会影响在响应消息中包含哪些头部。 本文讨论过的和即将讨论的用于HTTP请求消息和响应消息中的头部仅仅是很小的一部分HTTP规范中定义了更多可用的头部可以查阅相关的RFC文档进行更详细的了解。 用户—服务器交互 身份认证和cookie 我们已经知道HTTP服务器是无状态的。这样的处理可以简化服务器程序的设计以便开发出更高性能的Web服务器软件。然而一个Web站点往往有标识其用户的需求因为其web服务器可能希望限制用户的访问也可能想要根据用户的身份来提供内容。HTTP提供了两种帮助服务器标识用户的机制:身份认证和cookle。 身份认证许多web站点要求用户提供一个用户名—口令对才能访问存放在其服务器中的文档。这种要求称为身份认证(authentication)。HTTP提供特殊的状态码和头部来帮助Web站点执行身份认证。我们通过查看一个例子来领会这些特殊的状态码和头部如何工作。假设有—个客户在请求来自某个服务器的一个对象而该服务器要求用户授予权限。 客户首先发送一个不合特殊头部的普通请求消息。服务器以空的附属体和一个“401Authorization Required”状态码作为响应。服务器还在这个响应消息中包含“个WWW-Authenticate:头部说明具体如何执行身份认证。这个头部的典型值是指出用户需要提供一个用户名—口令对。 客户收到这个响应消息后提示用户输入用户名和口令然后重新发送请求消息。这一回客户在请求消息中包含了一个Authorization:头部其中包含有用户输入的用户名和口令。 取得第一个对象后客户在同为请求该服务器上对象的后续请求中继续发送这个用户名—口令对。这个做法一般将持续到用户关闭浏览器为止。在浏览器未被关闭之前这个用户名—口令对是高速缓存着的因此浏览器不会每请求一个对象就提示用户输入一次用户名和口令。通过上述方式要求用户授权的Web站点就能标识出每个请求的用户了。 我们需要知道HTTP执行的是一种相当脆弱的身份认证方式不难攻破。现代有很多更为安全的认证方式我们会在以后介绍。 cookie是一种可让Web站点用来跟踪用户的候选机制定义在RFC 2109中。有些Web站点使用cookie其他Web站点则不用。下面查看一个例子。假设一个客户首次联系一个使用cookie的web站点。服务器会在其响应中包含一个Set—Cookie:头部。该头部的值可以是一个由Web服务器产生的客户标识数.例如: Set-Cookie:1678453 客户收到这个响应消息看到其中的Set-Cookie:头部和标识数后会在存放在客户主机中的某个特殊的cookie文件中添加一行。这一行一般包含服务器主机的主机名和这个与用户关联的标识数。在一段时间(如一个星期)之后请求同一个服务器时由同一个用户启动的新客户会在请求消息中包含一个cookie头部其值为早先由该服务器产生的标识数例如:Cookie:1678453 在这种方式中服务器并不知道提出请求的用户的用户名但是它确实知道该用户与一个星期前提出请求的用户是同一个。 Web服务器有多个使用coohe的目的: ●如果服务器要求身份认证但又不想在同一用户每次访问本Web站点时都麻烦他输入用户名和口令那么可以设置一个cookie。 ●如果服务器想要记住用户的偏好以便在他们后续访问期间有目的地提供广告那么可以设置一个cookie。 ●如果web站点提供购物服务那么服务器可以使用cookie跟踪用户购买的物品就是建立一个虚拟的购物车。 需指出的是cookie不适用于会从不同主机访问同一web站点的游动用户。这种情况下该web站点会把同一个用户在不同主机上的使用看成是由新的用户执行的。 带条件的GET Web高速缓存技术通过就近存取先前取得的对象来降低对象检索延迟减少因特网上的web流量。Web的高速缓存既可以驻留在客户主机中也可以驻留在中间网络高速缓存服务器主机中。我们将在稍后讨论网络高速缓存这里只关注客户的高速缓存。 Web高速缓存在降低用户可感知的响应时间的同时却引入了一个新的问题——高速缓存中存放的对象的拷贝可能是过期的。换句话说存放在web服务器中的对象可能己在客户高速缓存下它的一个拷贝之后被修改了。幸运的是HTTP提供一个专门的机制使得在允许客户进行高速缓存的同时仍确保传递给浏览器的所有对象都是最新的。这个机制称为带条件的0ET(conditional GET)。满足条件(1)使用GET方法和(2)包含If-Modified-S1nce:头部的HTTP请求消息就是所谓的带条件的Get消息。 我们通过查看一个例子来说明带条件的GET如何工作向服务器请求一个尚未高速缓存的对象: GET /fruit/kiwi.gif HTTP/1.0 User—agent: Mozilla/4.0 接着web服务器把带这个对象的一个响应消息发送给客户: HTTP/1.0 200 OK Date: Thu, 13 Oct 2005 05:33:47 GMT Server: Apache/2.0.54 (Unix) Last-Modified:Thu, 13 Oct 2005 02:32:47 GMT Content-Type:image/gif (数据 数据 数据 数据 数据……) 客户把这个对象显示给用户同时把它保存在自己的本地高速缓存中客户还随该对象本身高速缓存最后修改日期与时间。一个星期之后同一个用户请求同一个对象而该对象仍然存放在高速缓存中。既然web服务器中的该对象有可能已在最近一个星期被修改过于是浏览器发出一个带条件的GET消息执行判定高速缓存的对象拷贝是否为最新的检查; GET /fruit/kiwi.gif HTTP/1.0 User—agent: Mozilla/4.0 If—Modlfied—Since:Thu, 13 Oct 2005 02:32:47 GMT 其中If—Modlfied—Since:头部的值就等于一个星期前由服务器发送的Last-Modified:头部的值。这个带条件的GET消息告知服务器只有在该对象自所指定的时间以来被修改了的前提下才发送它。假设该对象在这段时间内未曾被修改过那么服务器将发送一个附属体为空的响应消息给客户; HTTP/1.0 304 Not Modified Date: Thu, 20 Oct 2005 05:33:47 GMT Server: Apache/2.0.54 (Unix) 我们看到web服务器仍然发送——个响应消息作为带条件的GET消息的响应不过其中不包含所请求的对象。包含该对象只会浪费带宽并延长用户可感知的响应时间特别是在该对象很大的时候。注意这个响应消息的状态为“304 Not Modified”它告知客户可以放心使用所请求对象的高速缓存版本。 用Socket类实现HTTP协议客户端应用Http客户端程序已集成在Java语言中可以通过URLConnection类调用。遗憾的是由于SUN没有公布Http客户程序的源码它实现的细节仍是一个谜。本文根据HTTP协议规范用Java.net.Socket类实现一个HTTP协议客户端程序。1.Socket类:了解TCP/IP协议集通信的读者知道协议间的通信是通过Socket完成的。在Java.net包中Socket类就是对Socket的具体实现。它通过连接到主机后返回一个I/O流实现协议间的信息交换。2 . HTTP协议HTTP协议同其它TCP/IP协议集中的协议一样是遵循客户/服务器模型工作的。客户端发往服务端的信息格式如下:------------------------------请求方法 URL HTTP协议的版本号提交的元信息**空行**实体------------------------------请求方法是对这次连接工作的说明目前HTTP协议已经发展到1.1版它包括GET、HEAD、POST、DELETE、OPTIONS、TRACE、PUT七种。元信息是关于当前请求的信息。通过分析元信息可以检查实体数据是否完整接收过程是否出错类型是否匹配等。元信息的引入使HTTP协议通信更加稳妥可靠。实体是请求的具体内容。将上述报文发往Web服务器如果成功应答格式如下:--------------------------------HTTP协议的版本号 应答状态码 应答状态码说明接收的元信息**空行**实体--------------------------------以上报文发向客户端并且接收成功彼此间关闭连接完成一次握手。下面用最常用的GET方法来说明具体的报文应用----------------------------------GET http://www.youhost.com HTTP/1.0accept: www/source; text/html; image/gif; image/jpeg; */*User_Agent: myAgent**空行**-----------------------------------这个报文是向www.youhost.com主机请求一个缺省HTML文档。客户端HTTP协议版本号是1.0版元信息包括可接收的文件格式用户代理每一段之间用回车换行符分隔最后以一个空行结束。发向服务器后如果执行过程正常服务器返回以下代码:------------------------------------HTTP/1.1 200 OKDate: Tue, 14 Sep 1999 02:19:57 GMTServer: Apache/1.2.6Connection: closeContent-Type: text/html**空行**......------------------------------------HTTP/1.1表示这个HTTP服务器是1.1版200是服务器对客户请求的应答状态码OK是对应答状态码的解释之后是这个文档的元信息和文档正文。(相关应答状态码和元信息的解释请参阅Inetrnet标准草案:RFC2616)。3. HTTP客户端程序:import java.net.*;import java.io.*;import java.util.Properties;import java.util.Enumeration;public class Http {protected Socket client;protected BufferedOutputStream sender;protected BufferedInputStream receiver;protected ByteArrayInputStream byteStream;protected URL target;private int responseCode-1;private String responseMessage;private String serverVersion;private Properties header new Properties();public Http() { }public Http(String url) {GET(url) ;}/* GET方法根据URL会请求文件、数据库查询结果、程序运行结果等多种内容 */public void GET(String url) {try {checkHTTP(url);openServer(target.getHost(),target.getPort() );String cmd GET getURLFormat(target) HTTP/1.0/r/n getBaseHeads()/r/n;sendMessage(cmd);receiveMessage();}catch(ProtocolException p) {p.printStackTrace();return;}catch(UnknownHostException e) {e.printStackTrace();return;}catch(IOException i)i.printStackTrace();return;}}/** HEAD方法只请求URL的元信息不包括URL本身。若怀疑本机和服务器上的* 文件相同用这个方法检查最快捷有效。*/public void HEAD(String url) {try {checkHTTP(url);openServer(target.getHost(),target.getPort() );String cmd HEAD getURLFormat(target) HTTP/1.0/r/ngetBaseHeads()/r/n;sendMessage(cmd);receiveMessage();}catch(ProtocolException p) {p.printStackTrace();return;}catch(UnknownHostException e) {e.printStackTrace();return;}catch(IOException i)i.printStackTrace();return;}}/** POST方法是向服务器传送数据以便服务器做出相应的处理。例如网页上常用的* 提交表格。*/public void POST(String url,String content) {try {checkHTTP(url);openServer(target.getHost(),target.getPort() );String cmd POST getURLFormat(target) HTTP/1.0/r/ngetBaseHeads();cmd Content-type: application/x-www-form-urlencoded/r/n;cmd Content-length: content.length() /r/n/r/n;cmd content/r/n;sendMessage(cmd);receiveMessage();}catch(ProtocolException p) {p.printStackTrace();return;}catch(UnknownHostException e) {e.printStackTrace();return;}catch(IOException i)i.printStackTrace();return;}}protected void checkHTTP(String url) throws ProtocolException {try {URL target new URL(url);if(targetnull || !target.getProtocol().toUpperCase().equals(HTTP) )throw new ProtocolException(这不是HTTP协议);this.target target;}catch(MalformedURLException m) {throw new ProtocolException(协议格式错误);}}/** 与Web服务器连接。若找不到Web服务器InetAddress会引发UnknownHostException* 异常。若Socket连接失败会引发IOException异常。*/protected void openServer(String host,int port) throwsUnknownHostException,IOException {header.clear();responseMessage; responseCode-1;try {if(client!null) closeServer();if(byteStream ! null) {byteStream.close(); byteStreamnull;}InetAddress address InetAddress.getByName(host);client new Socket(address,port-1?80:port);sender new BufferedOutputStream(client.getOutputStream());receiver new BufferedInputStream(client.getInputStream());}catch(UnknownHostException u) {throw u;}catch(IOException i) {throw i;}}/* 关闭与Web服务器的连接 */protected void closeServer() throws IOException {if(clientnull) return;try {client.close(); sender.close(); receiver.close();}catch(IOException i) {throw i;}clientnull; sendernull; receivernull;}protected String getURLFormat(URL target) {String spec http://target.getHost();if(target.getPort()!-1)spec:target.getPort();return spectarget.getFile();}/* 向Web服务器传送数据 */protected void sendMessage(String data) throws IOException{sender.write(data.getBytes(),0,data.length());sender.flush();}/* 接收来自Web服务器的数据 */protected void receiveMessage() throws IOException{byte data[] new byte[1024];int count0;int word-1;// 解析第一行while( (wordreceiver.read())!-1 ) {if(word/r||word/n) {wordreceiver.read();if(word/n) wordreceiver.read();break;}if(count data.length) data addCapacity(data);data[count](byte)word;}String message new String(data,0,count);int mark message.indexOf(32);serverVersion message.substring(0,mark);while( mark responseCode Integer.parseInt(message.substring(mark1,mark4));responseMessage message.substring(mark,message.length()).trim();// 应答状态码和处理请读者添加switch(responseCode) {case 400:throw new IOException(错误请求);case 404:throw new FileNotFoundException( getURLFormat(target) );case 503:throw new IOException(服务器不可用 );}if(word-1) throw new ProtocolException(信息接收异常终止);int symbol-1;count0;// 解析元信息while( word!/r word!/n word-1) {if(word/t) word32;if(countdata.length) data addCapacity(data);data[count] (byte)word;parseLine: {while( (symbolreceiver.read()) -1 ) {switch(symbol) {case /t:symbol32; break;case /r:case /n:word receiver.read();if( symbol/r word/n) {wordreceiver.read();if(word/r) wordreceiver.read();}if( word/r || word/n || word32) break parseLine;symbol32; break;}if(countdata.length) data addCapacity(data);data[count] (byte)symbol;}word-1;}message new String(data,0,count);mark message.indexOf(:);String key null;if(mark0) key message.substring(0,mark);mark;while( mark String value message.substring(mark,message.length() );header.put(key,value);count0;}// 获得正文数据while( (wordreceiver.read())!-1) {if(count data.length) data addCapacity(data);data[count] (byte)word;}if(count0) byteStream new ByteArrayInputStream(data,0,count);datanull;closeServer();}public String getResponseMessage() {return responseMessage;}public int getResponseCode() {return responseCode;}public String getServerVersion() {return serverVersion;}public InputStream getInputStream() {return byteStream;}public synchronized String getHeaderKey(int i) {if(iheader.size()) return null;Enumeration enum header.propertyNames();String key null;for(int j0; ji; j)key (String)enum.nextElement();return key;}public synchronized String getHeaderValue(int i) {if(iheader.size()) return null;return header.getProperty(getHeaderKey(i));}public synchronized String getHeaderValue(String key) {return header.getProperty(key);}protected String getBaseHeads() {String inf User-Agent: myselfHttp/1.0/r/nAccept: www/source; text/html; image/gif; */*/r/n;return inf;}private byte[] addCapacity(byte rece[]){byte temp[] new byte[rece.length1024];System.arraycopy(rece,0,temp,0,rece.length);return temp;}}注: 程序中只实现GET、HEAD、POST三种方法。其他几种因不常使用暂且忽略。 HTTP超文本传输协议HTTPHypertext Transfer Protocol 超文本传输协议HTTP是应用层协议由于其简捷、快速的方式适用于分布式和合作式超媒体信息系统。自 1990 年起 HTTP 就已经被应用于 WWW 全球信息服务系统。 HTTP 允许使用自由答复的方法表明请求目的它建立在统一资源识别器URI提供的参考原则下作为一个地址URL或名字URN用以标志采用哪种方法它用类似于网络邮件和多用途网际邮件扩充协议MIME的格式传递消息。 HTTP 也可用作普通协议实现用户代理与连接其它 Internet 服务如 SMTP 、 NNTP 、 FTP 、 GOPHER 及 WAIS 的代理服务器或网关之间的通信允许基本的超媒体访问各种应用提供的资源同时简化了用户代理系统的实施。 HTTP 是一种请求 / 响应式的协议。一个客户机与服务器建立连接后发送一个请求给服务器请求的格式是统一资源标识符URI、协议版本号后面是类似 MIME 的信息包括请求修饰符、客户机信息和可能的内容。服务器接到请求后给予相应的响应信息其格式是一个状态行包括信息的协议版本号、一个成功或错误的代码后面也是类似 MIME 的信息包括服务器信息、实体信息和可能的内容。 HTTP 的第一版本 HTTP/0.9 是一种简单的用于网络间原始数据传输的协议。而由 RFC 1945 定义的 HTTP/1.0 在原 HTTP/0.9 的基础上有了进一步的改进允许消息以类 MIME 信息格式存在包括请求 / 响应范式中的已传输数据和修饰符等方面的信息。但是 HTTP/1.0 没有充分考虑到分层代理服务器、高速缓冲存储器、持久连接需求或虚拟主机等方面的效能。相比之下 HTTP/1.1 要求更加严格以确保服务的可靠性。关于安全增强版的 HTTP 即S-HTTP将在相关文件中再作介绍。 协议结构 HTTP报文由从客户机到服务器的请求和从服务器到客户机的响应构成。 请求报文格式如下请求行通用信息头请求头实体头报文主体 请求行以方法字段开始后面分别是 URL 字段和 HTTP 协议版本字段并以 CRLF 结尾。SP 是分隔符。除了在最后的 CRLF 序列中 CF 和 LF 是必需的之外其他都可以不要。有关通用信息头请求头和实体头方面的具体内容可以参照相关文件。 应报文格式如下状态行通用信息头响应头实体头报文主体 状态码元由3位数字组成表示请求是否被理解或被满足。原因分析是对原文的状态码作简短的描述状态码用来支持自动操作而原因分析用来供用户使用。客户机无需用来检查或显示语法。有关通用信息头响应头和实体头方面的具体内容可以参照相关文件。 相关协议WWW、FTP、STMP、NNTP、Gopher、WAIS、DNS、S-HTTP组织来源HTTP 定义在 IETF (http://www.ietf.org) 的 RFC 1945和2616中。相关链接http://www.javvin.com/protocol/rfc1945.pdf Hypertext Transfer Protocol – HTTP 1.0http://www.javvin.com/protocol/rfc2616.pdf Hypertext Transfer Protocol – HTTP 1.1 再分享一下我老师大神的人工智能教程吧。零基础通俗易懂风趣幽默还带黄段子希望你也加入到我们人工智能的队伍中来https://blog.csdn.net/jiangjunshow