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客户和服务器也能配置成非持续连接。

采用非持续连接的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文件的时间。

采用持续连接的HTTP

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

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

HTTP报文格式

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

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服务器上的对象。

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,如下图:

HTTP基础及telnet基本用法的更多相关文章

  1. Hadoop基础-MapReduce的Partitioner用法案例

    Hadoop基础-MapReduce的Partitioner用法案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Partitioner关键代码剖析 1>.返回的分区号 ...

  2. Hadoop基础-MapReduce的Combiner用法案例

    Hadoop基础-MapReduce的Combiner用法案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编写年度最高气温统计 如上图说所示:有一个temp的文件,里面存放 ...

  3. Java基础-synchronized关键字的用法(转载)

    synchronized--同步 顾名思义是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 当synchronized修饰 this或者非静态方法或者是一个实例的时候,所同步的锁是加在 ...

  4. MySQL基础之STRAIGHT JOIN用法简介

    MySQL基础之STRAIGHT JOIN用法简介 引用mysql官方手册的说法: STRAIGHT_JOIN is similar to JOIN, except that the left tab ...

  5. 《Java基础——break与continue用法详解》

    Java基础--break与continue用法详解       1. break语句: 规则: 1. 仅用于循环语句和switch语句当中,用于跳出循环. 2. 当只有一层循环时,则直接跳出循环,不 ...

  6. linux学习基础6之sed用法详解

    1 sed 又称为流编辑器,它逐行将文本文件中的行读取到模式空间中间去,将符合编辑条件的行进行编辑后输出到显示器上来.默认sed不编辑原文件只处理模式空间中的内容. 2 sed用法 sed [opti ...

  7. C基础--关于typedef的用法总结

    转自:http://blog.csdn.net/wangqiulin123456/article/details/8284939 在C还是C++代码中,typedef都使用的很多,在C代码中尤其是多. ...

  8. python基础之 sys.argv[]用法

    sys.argv[]是用来获取命令行参数的,sys.argv[0]表示代码本身文件路径,所以参数从1开始. arg[1]表示第一个命令行参数 arg[1][2:] 表示取第一个命令行参数,但是去掉前两 ...

  9. 软件测试必备-前端知识点之css基础及ps的用法

    CSS 一. css定义 css样式表.层叠样式表,级联样式表 二. css基础语法 1. 写style标签,放在head标签里面的最后位置 2. 自己写的css代码,放在style标签里面 三. c ...

随机推荐

  1. 微信小程序开发注意事项(优化项)

    最近公司有一个小程序开发项目,自己也自学了不少,有一些开发小心得,记录在这里. 小程序开发中注意: 1,setData 小程序视图层和逻辑层在两个独立的模块,并不具备数据直接传递的,setData相当 ...

  2. 百万年薪python之路 -- 模块二

    1. 序列化模块 什么是序列化呢? 序列化的本质就是将一种数据结构(如字典.列表)等转换成一个特殊的序列(字符串或者bytes)的过程就叫做序列化. 为什么要有序列化模块? 如果你写入文件中的字符串是 ...

  3. javascript获取坐标/滚动/宽高/距离

    坐标(鼠标/触摸) event.screenX 鼠标/触摸,相对于显示屏的X坐标 event.screenY 鼠标/触摸,相对于显示屏的Y坐标 event.clientX 鼠标/触摸,相对于浏览器视口 ...

  4. C++ 11标准

    C++11,也称为C++0x.为目前C++编程语言的最新正式标准(ISO/IEC 14882:2011).它将取代第二版标准ISO/IEC 14882:2003(第一版ISO/IEC 14882:19 ...

  5. 设计模式(十三)Visitor模式

    Visitor模式可以用来把数据结构与处理分离开.通俗来说就是编写一个访问者类来访问数据结构中的元素,并把对各元素的处理交给访问者类.这样,当需要增加新的处理时,只需要编写新的访问者,然后让数据结构可 ...

  6. js奥义:原型与原型链(2)

    回顾:上一篇讲了原型对象与prototype和__proto__(传送门 )三者之间的关系 三:constructor constructor [kənˈstrʌktə(r)] :构造器,  这是子类 ...

  7. ArcGIS制作地形图【详细步骤】

    结果图: 详细步骤: 一.在ArcSence中加载带有投影坐标系的dem数据 Dem的属性设置为下图可有上面的效果. 二.提取栅格范围 找到工具[3D Analyst][转换][栅格范围]双击打开设置 ...

  8. Python调试工具

    1. 日志 通过日志或者print来打印变量.必要时可以打印locals()和globals() 建议使用logging.debug()来代替print,这样到了正式环境,就可以统一删除这些日志. 2 ...

  9. nginx原理和优化

    Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是 ...

  10. SpringBoot系列之@Value和@ConfigurationProperties

    继上一篇博客SpringBoot系列之YAML配置用法之后,再写一篇@Value.@ConfigurationProperties的对比博客 这两个主键都是可以获取配置文件属性的,不过是有比较大的区别 ...