http 传输原理及格式
HTTP是Web协议集中的重要协议,它是从客户机/服务器模型发展起来的。客户机/服务器是运行一对相互通信的程序,客户与服务器连接时,首先,向服务器提出请求,服务器根据客户的请求,完成处理并给出响应。浏览器就是与Web服务器产生连接的客户端程序,它的端口为TCP的80端口。举一个大家都很常见的例子,浏览器与Web服务器之间所遵循的协议就是HTTP。
Web的应用层协议HTTP是Web的核心。
HTTP在Web的客户程序和服务器程序中得以实现。运行在不同端系统上的客户程序和服务器程序通过交换HTTP消息彼此交流。HTTP定义这些消息的结构以及客户和服务器如何交换这些消息。HTTP定义Web客户(即浏览器)如何从web服务器请求Web页面,以及服务器如何把Web页面传送给客户。
HTTP协议的优点就是可以解决传输数据的准确性、安全性较高、而且有处理网络拥塞的能力。这主要的原因就是HTTP协议传输数据的时候,是由HTTP都把TCP作为底层的传输协议。HTTP客户首先发起建立与服务器TCP连接。一旦建立连接,浏览器进程和服务器进程就可以通过各自的套接字来访问TCP。如前所述,客户端套接字是客户进程和TCP连接之间的“门”,服务器端套接字是服务器进程和同一TCP连接之间的门。客户往自己的套接字发送HTTP请求消息,也从自己的套接字接收HTTP响应消息。类似的,服务器从自己的套接字接收HTTP请求消息,也往自己的套接字发送HTTP响应消息。客户或服务器一旦把某个消息送入各自的套接字,这个消息就完全落入TCP的控制之中。
TCP给HTTP提供一个可靠的数据传输服务;这意味着由客户发出的每个HTTP请求消息最终将无损地到达服务器,由服务器发出的每个HTTP响应消息最终也将无损地到达客户。我们可从中看到分层网络体系结构的一个明显优势——HTTP不必担心数据会丢失,也无需关心TCP如何从数据的丢失和错序中恢复出来的细节。HTTP/1.1服务器端处理请求时按照收到的顺序进行,这就保证了传输的正确性。当然,服务器端在发生连接中断时,会自动的重传请求,保证数据的完整性。
值得注意的是HTTP协议的建立连接方式也非常特别,在早先的HTTP/1.0版本中使用的是非持久连接,而到了HTTP/1.1时非持久连接和持久连接都被支持,但默认使用持久连接。在此要说明非持久连接大概的过程是,举一个浏览网页的例子。首先客户由与TCP连接相关联的本地套接字发出—个HTTP请求消息;其次,服务器接受请求并且经由同一个套接字发送响应消息;然后HTTP服务器告知TCP关闭这个TCP连接(不过TCP要到客户收到刚才这个响应消息之后才会真正终止这个连接);这时HTTP客户经由同一个套接字接收这个响应消息后,TCP连接随后终止。该消息明确标明所封装的对象是一个什么样的文件。客户从中取出这个文件,加以分析后发现其中的真正内容的引用。然后再对这些内容申请连接,最后浏览器就可以显示出网页的内容了,假如网页的内容是由5幅图片组成的那么完成对网页的浏览就需要有6次TCP的连接,这是HTTP/1.0版本的做法。
在HTTP/1.1中,在持久连接情况下,服务器在发出响应后让TCP连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。整个Web页面(上例中为包含一个基本HTML文件和5个图像的页面)可以通过单个持久TCP连接发送,甚至存放在同一个服务器中的多个web页面也可以通过单个持久TCP连接发送。通常,HTTP服务器在某个连接闲置一段特定时间后关闭它,而这段时间通常是可以配置的。持久连接分为不带流水线(without pipelining)和带流水线(with pipelining)两个版本。如果是不带流水线的版本,那么客户只在收到前一个请求的响应后才发出新的请求。这种情况下,web页面所引用的每个对象(上例中的5个图像)都经历1个RTT的延迟,用于请求和接收该对象。与非持久连接2个RTT的延迟相比,不带流水线的持久连接已有所改善,不过带流水线的持久连接还能进一步降低响应延迟。不带流水线版本的另一个缺点是,服务器送出一个对象后开始等待下一个请求,而这个新请求却不能马上到达。这段时间服务器资源便闲置了。HTTP/1.1的默认模式使用带流水线的持久连接。这种情况下,HTTP客户每碰到一个引用就立即发出一个请求,因而HTTP客户可以一个接一个紧挨着发出各个引用对象的请求。服务器收到这些请求后,也可以一个接一个紧挨着发出各个对象。如果所有的请求和响应都是紧挨着发送的,那么所有引用到的对象一共只经历1个RTT的延迟(而不是像不带流水线的版本那样,每个引用到的对象都各有1个RTT的延迟)。另外,带流水线的持久连接中服务器空等请求的时间比较少。与非持久连接相比,持久连接(不论是否带流水线)除降低了1个RTT的响应延迟外,缓启动延迟也比较小。其原因在于既然各个对象使用同一个TCP连接,服务器发出第一个对象后就不必再以一开始的缓慢速率发送后续对象。相反,服务器可以按照第一个对象发送完毕时的速率开始发送下一个对象。
从上面的例子不难看出,非持久连接中用户的点击导致浏览器发起建立一个与Web服务器的TCP连接,这里涉及一个三次握手的过程:首先是客户向服务器发送一个小的冗余消息,接着是服务器向客户确认并响应一个小的TCP消息,最后是客户向服务器回确认。三次握手过程的前两次结束时,流逝的时间为1个RTT。此时客户把HTTP请求消息发送到TCP连接中,客户接着把三次握手过程最后一次中的确认捎带,在包含这个消息的数据分节中发送出去。服务器收到来自TCP连接的请求消息后,把相应的HTML文件发送到TCP连接中,服务器接着把对早先收到的客户请求的确认捎带在包含该HTML文件的数据分节中发送出去。这个HTTP请求顺应交互也花去1个RTT时间。很容易就能看出持久连接在时间损耗上的优势了。
另外一个非常重要的地方就是HTTP协议的请求头以及响应头的格式。如果不清楚请求头的格式就无法向服务器端准确地发送下载请求;同时响应头的获得信息,对下载工具下一步的处理也至关重要。下面列出HTTP请求消息:
GET/somedir/page.htmlHTTP/1.1
Host:www.hhit.edu.cn
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字段中标识。本例中浏览器实现的是HTTP/1.1版本。
上面例子中的请求消息有四行他们的意思分别是:
头部行Host:www.hhit.edu.cn存放所请求对象的主机。
请求消息中包含头部Connection:close是在告知服务器本浏览器不想使用持久连接;服务器发出所请求的对象后应关闭连接。尽管产生这个请求消息的浏览器实现的是HTTP/1.1版本,它还是不想使用持久连接。
User-agent头部行指定用户代理,也就是产生当前请求的浏览器的类型。本例的用户代理是Mozilla/4.0,它是Nelscape浏览器的一个版本。这个头部行很有用,因为服务器实际上可以给不同类型的用户代理发送同一个对象的不同版本(这些不同版本位用同一个URL寻址)。
最后,Accept-languag:头部行指出要是所请求对象有简体中文版本,那么用户宁愿接收这个版本;如果没有这个语言版本,那么服务器应该发送其默认版本。Accept-languag:仅仅是HTTP的众多内容协商头部之一。
HTTP协议请求消息的一般格式如图:
图 HTTP协议的请求信息格式
值得注意的是在请求消息的最后是附属体,在我们给出的例子中并没有这一项。是因为,附属体不在GET方法中使用,而是在POST方法中使用。POST方法适用于需由用户填写表单的场合,如往google搜索引擎中填入待搜索的词。用户提交表单后,浏览器就像用户点击了超链接那样仍然从服务器请求一个Web页面,不过该页面的具体内容却取决于用户填写在表单各个字段中的值。如果浏览器使用POST方法提出该请求,那么请求消息附属体中包含的是用户填写在表单各个字段中的值。
HTTP协议的响应消息和请求消息有所不同,下面是一个典型的响应消息:
HTTP/1.1 200 OK
Connection:close
Date:Thu,13Oct200503:17:33GMT
Server:Apache/2.0.54(Unix)
Last-Modified:Mon,22Jun199809;23;24GMT
Content-Length:682l
Content-Type:text/html
(数据数据数据数据数据…………)
这个响应消息分为3部分:1个起始的状态行(Status Line),6个头部行、1个包含所请求对象本身的附属体。状态行有3个字段:协议版本字段、状态码字段、原因短语字段。本例的状态行表明,服务器使用HTTP/1.1版本,状态码(Status Codes)200表示响应过程完全正常(也就是说服务器找到了所请求的对象,并正在发送)。
在上面的响应消息中头部行的意思分别是:
服务器使用Connection:close头部行告知客户自己将在发送完本消息后关闭TCP连接。
Date头部行:指出服务器创建并发送本响应消息的日期和时间。注意,这并不是对象本身的创建时间或最后修改时间,而是服务器把该对象从其文件系统中取出,插入响应消息中发送出去的时间。
Server头部行:指出本消息是由Apache服务器产生的;它与HTTP请求消息中的User-agent头部行类似。
Last-Modified头部行:指出对象本身的创建或最后修改日期或时间。Last-Modified头部对于对象的高速缓存至关重要,且不论这种高速缓存是发生在本地客户主机上还是发生在网络高速缓存服务器主机(也就是代理服务器主机)上。
Content-Length头部行:指出所发送对象的字节数。
Content-Type头部行:指出包含在附属体中的对象是HTML文本。对象的类型是由Content—Type头部而不是由文件扩展名正式指出的。
HTTP响应消息格式如图:
图 HTTP协议的响应信息格式
图 完整的HTTP请求响应内容
在响应消息中的状态行明显多出了明显多出了状态码(Status Codes)和原因短语,是因为在请求的信息可能存在着很多情况需要区分开,这样也便于用户能够清楚地知道请求的情况以及出错的原因,响应消息中的状态码和原因短语指示相应请求的处理结果。当服务器响应时,其状态行的信息为HTTP的版本号,状态码,及解释状态码的简单说明。现将5类状态码详细列出:
1XX客户方错误
100 继续
101 交换协议
2XX成功
200 OK
201 已创建
202 接收
203 非认证信息
204 无内容
205 重置内容
206 部分内容
3XX重定向
300 多路选择
301 永久转移
302 暂时转移
303 参见其它
304 未修改(Not Modified)
305 使用代理
4XX客户方错误
400 错误请求(Bad Request)
401 未认证
402 需要付费
403 禁止(Forbidden)
404 未找到(Not Found)
405 方法不允许
406 不接受
407 需要代理认证
408 请求超时
409 冲突
410 失败
411 需要长度
412 条件失败
413 请求实体太大
414 请求URL太长
415 不支持媒体类型
5XX服务器错误
500 服务器内部错误
501 未实现(Not Implemented)
502 网关失败
504 网关超时
505 HTTP版本不支持