HTTP协议

目录

Web和HTTP

HTTP概况

HTTP使用TCP传输服务

HTTP是无状态协议 

 非持续连接和持续连接

 HTTP报文格式

HTTP请求报文

HTTP响应报文

telnet模拟HTTP请求

用户与服务器的交互Cookie

Web缓存

Web缓存器

条件GET方法


Web和HTTP

World Wide Web是由Tim Berners-Lee发明的,Web使得网页可以互相链接,从而形成了极其庞大的信息网络和内容网络,今天也被发展成为服务网络。Web极大地改变了人们与工作环境内外交流的方式,它将因特网从只是很多数据网之一的地位提升到仅有的一个数据网。Web没有任何商业性的需求,在这里也是要向这位Berners-Lee致敬。

HTTP概况

Web的应用层协议是超文本传输协议(HyperText Transfer Protocol,HTTP),它是Web的核心。HTTP由两个程序实现:客户程序和服务程序。二者运行在不同的端系统中,通过交换HTTP报文进行会话。HTTP定义了报文的结构以及客户和服务器进行报文交换的方式。在介绍HTTP之前,先讲一下一些Web术语。

对象(object)
一个文件,如HTML文件、JPEG图片、一段视频等等

URL(Uniform Resoure Locator,统一资源定位器):
URL可以定位对象所在位置。
格式:Scheme[协议]://host[主机的域名或IP地址]:port[端口号]/abs_path[绝对路径]。
如:www.someSchool.edu/someDepartment/picture.gif   (主机名/路径)
如果没有具体表明协议,则默认为http

Web页面(Web page)
由多个对象组成,包含一个HTML基本文件(HTML file)以及几个引用对象。HTML基本文件通过对象的URL地址引用页面中的其他对象。可以理解为PPT制作时的超链接。

Web浏览器(Web browser)
HTTP的客户端,请求、接受、解析、展示Web对象

Web服务器(Web server)
HTTP的服务端,存储Web对象,每个对象由URL寻址,响应客户的请求,发送对象。

HTTP使用TCP传输服务

HTTP定义了Web客户向Web服务器请求页面的方式,以及服务器向客户传送Web页面的方式。
HTTP使用TCP作为它的支撑运输协议。HTTP客户发出与服务器建立TCP连接的请求,一旦建立连接,该浏览器和服务器进程就可以通过套接字接口Socket访问TCP。
客户向它的套接字接口发送HTTP请求报文,并从该接口接收服务器的HTTP相应报文。
服务器向它的套接字接口发送HTTP相应报文,并从该接口接收客户的HTTP请求报文。

TCP为HTTP提供可靠数据传输服务。这意味着一个客户进程发出的每个HTTP请求报文最终能完整地到达服务器;类似地服务器进程发出地每个HTTP响应报文最终能完整的到达客户。这就是分层结构最大的优点,HTTP协议不用担心数据丢失,也不关注TCP从网络的数据丢失和乱序故障中恢复的细节。

HTTP是无状态协议 

需要强调的是服务器向客户发送被请求的文件,但不会存储任何关于该客户的状态信息(如访访问的时间,浏览记录等)。假如一个客户向服务器发起请求,服务器做出响应,几秒后客户又向服务器请求同一个对象,服务器并不因为刚刚提供了而不做出响应,服务器会选择重新发送。由于HTTP服务器并不保存关于客户的任何和信息,所以HTTP又是一种无状态协议(statsless prrotocol)。

为什么HTTP是无状态协议?首先有状态的协议更为复杂,不仅需要维护状态(历史信息),另外如果客户或者服务器失效(如重启),会产生状态的不一致,解决不一致的代价很高。既然如此,我们购物车的记录(历史信息)是怎么保存的呢?这个则是使用了cookie技术(下文有讲)。

 非持续连接和持续连接

HTTP1.0或者说是早期版本使用非持久连接,每个TCP连接最多传输一个对象

而HTTP1.1版本则默认使用持久连接,每个TCP连接可以传输多个对象。

接下来我们先来详细描述一下最基本的非持久连接的请求响应过程。

假设用户在浏览器中输入URL:www.someSchool.edu/someDepartment/home.index,若这个基本的HTML文件包含文本和指向10个JPEG图片的链接。

 上述完成了一次TCP请求响应的流程,但当客户端收到对象解析后发现要有10个指向JPEG对象的超链接。但是客户并没有请求过这10个对象。而此时TCP连接已经关闭,所以要为每个JPEG对象重复上述流程。

可以看出每个TCP连接只传输一个请求报文和一个响应报文。因此在这个例子中客户请求Web页面时,产生了11个TCP连接。我们来简单的估算一个从客户请求HTML基本文件到客户收到整个文件所花费的时间。我们定义往返时间(Roud-Trip Time,RTT)指一个短分组从客户到服务器然后再返回客户所花费的时间。

由此可以看出一个TCP连接需要2个RTT和传输文件时间,对于上述例子,则需要22个RTT+传输所有文件所需要的时间。

不难看出非持久连接每个对象都需要2个RTT以上的时间,需要22个RTT以上的时间才能获得整个网页,耗时较大,另外操作系统要为每个TCP连接开销资源,对服务器会产生一定的负担。这时就会有人想,什么不干脆并行操作,同时建立10个TCP连接,一次获取10个对象,这样就只需要2个RTT的时间就能获取10个对象了。但是本来一个客户只需要建立一个TCP连接,现在突然增加到10个,这会对服务器产生巨大的压力。由此我们有了持续性连接。

持续性连接就是服务器发送响应后保持该TCP连接打开,后序的HTTP消息可以通过这个连接发送。若采用持久性连接,上述案例流程如下:

 上述流程客户只有收到前一个响应后,才发送新的请求,即每个请求一个引用对象需要至少一个RTT的时间,总时间为12个RTT+传输所有文件的时间,于之前的22个RTT+传输所有文件的时间相比缩短了很多。当然还有时间更短的带有流水机制的持久性连接,即客户只要遇到一个引用对象就尽快发出请求。理想状态下,收到所有的引用对象只需要消耗1个RTT。

 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

请求报文的第一行叫请求行(request line),后继的行叫做首部行(header line)。

请求行有3个字段:方法字段、URL字段、HTTP版本字段。方法字段可以去几种不同的值,包括GET、POST、HEAD、PUT、DELETE。

GET          请求获取Request-URI所标识的资源
POST        在Request-URI所标识的资源后附加新的数据
HEAD       请求获取由Request-URI所标识的资源的响应消息报头
PUT          请求服务器存储一个资源,并用Request-URI作为其标识
DELETE   请求服务器删除Request-URI所标识的资源

HTTP版本字段就是采用1.0或者1.1版本。

首部行的Host:www.someschool.edu指明对象所在的主机。我们不是已经建立了TCP连接了吗(先建立连接后请求,详细见HTTP概述),为什么还要标识主机?是不是多此一举了?首部行提供的信息是Web代理高速缓存所要求的(后文介绍)。

首部行的Connection:close,表明了连接状态,close则是告诉服务器不需要使用持续连接,服务器发送完本次请求的对象后,即可关闭这个TCP连接。Connection另一个常见取值为keep-alive,即保持持续性连接。

首部行的User-agent则是用来指明用户代理,即向服务器发送请求的浏览器的类型。服务器可以有效地为不同类型的用户代理实际发送相同对象的不同版本。

HTTP请求报文的通用格式如下:

 有人可能注意到“实体主体”这一部分,实体主主体只有向服务器传输数据时才会用到,如输入账号、密码,相关的数据就会放在实体主体部分。常用的GET方法实体主体为空,因为GET是请求对象,并不传输数据给服务器,POST方法则会使用实体主体。

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: 6821
Content-Type: text/html
(data data data data......)

响应报文有三部分:状态行(status line),首部行(header line),实体体(entity body)。

状态行有3个字段:协议版本字段(HTTP/1.1)、状态码(200)、相应状态信息(OK),一个相应状态信息对应一个状态码:

200OK                         请求成功
301Moved Permanently请求的对象被永久转移,新的URL定义在响应报文的Location首部行中
400Bad Request一个通用差错代码,指示该请求不能被服务器理解
404Not Found被请求的文档不在服务器上
505HTTP Version Not Supported服务器不支持请求报文使用的HTTP协议版本

首部行的Connection:close首部行告诉客户,发送完报文后将关闭这个TCP连接。

Date:首部行指示服务器产生并发送响应报文的日期和时间。也就是服务器从文件系统中检索到对象,插入到响应报文,并发送该响应报文的时间,与之后的Last-Modified不同。

Server:首部行指示该报文是由一台Apache Web服务器产生的

Last-Modified:对象创建或最后修改日期和时间。这一点对Web高速缓存来说很重要可以更新对象(后文介绍)

实体体是报文的主要部分,包含了锁清秋的对象本身。

HTTP响应报文通用格式如下:

telnet模拟HTTP请求

(最好在Linux操作系统上测试)

1、Ctrl+Alt+T打开shell,输入如下命令:

telnet www.baidu.com 80

2、相应如下,然后按下Ctrl+']' 

Trying 112.80.248.76...
Connected to www.a.shifen.com.
Escape character is '^]'.

3、输入HTTP请求协议

GET /index.php HTTP/1.1
Host: www.baidu.com    
Connection:close

得到响应如下:

用户与服务器的交互Cookie

在HTTP概述中有讲到HTTP协议是无状态的,也就是你花了1h在购物车添加了10件物品,但是再次打开后,购物车却是空的,这就是因为HTTP协议无状态,没有保存之前的浏览、购物信息。

Web站点通常希望能够识别用户,可能是因为服务器希望限制用户的访问,或者因为它希望把内容与用户身份联系起来。为此,HTTP使用了cookie。

cookie技术的4个组件:

1、HTTP请求报文的头部行

2、HTTP响应报文的头部行

3、保存在客户端主机上的cookie文件,由浏览器管理

4、Web服务器端的后台数据库

我们假设A首次通过浏览器与Amazon.com联系。则使用cookie技术的HTTP协议大致流程如下:

1、若A过去访问过eBay站点。当请求报文到达该Amazon Web服务器时,该Web站点将产生一个唯一的识别码,并以此作为索引在它的后端数据库中产生一个表项。

2、接下来Amazon Web服务器用一个包含Set-cookie:首部的HTTP响应报文对A的浏览器进行响应,其中Set-cookie:首部含有该识别码。

3、当A的浏览器收到了该HTTP响应报文时,它会看到该Set-cookie:首部。该浏览器在它管理的特点cookie文件中添加一行,该行包含服务器的主机名和在Set-cookie:首部中的识别码。

若A继续访问Amazon网站,每请求一个Web网页,其浏览器就会从该cookie文件中获取A在Amazon网占的识别码,并放到HTTP请求报文中包含识别码的cookie首部行中。Amazon Web服务器通过识别码在后端数据库索引A在该网站的活动状态。

简而言之每一个用户在不同的网站都有一个识别码,可以理解为身份证,每次访问网页(除了第一次)Web服务器都会通过该识别码来确定用户,并通过该识别码,在后端数据库中索引相应的状态信息。举一个不恰当的例子:小王在淘宝网的识别码为0001,并购买了肉,则后端数据库就可能这样存储:00001 -- 肉。

尽管cookie能够简化用户的因特网活动,但是可能会侵害用户隐私,现在对cookie的存在备受争议。

Web缓存

Web缓存器

Web缓存器(Web cache)也叫服务代理器(proxy server),它是能够代表初始Web服务器来满足HTTP请求的网络实体。Web缓存器有自己的磁盘储存空间,并在存储空间中保存最近请求过的对象的副本。本来客户浏览器通过HTTP协议向服务器进行网页请求,通过配置浏览器,使得浏览器的请求首先被定向到该Web缓存器。举个例子,假设浏览器正在请求对象http://www.someschool.edu/campus.gif,流程大致如下:

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

2、Web缓存器进行检查,查看本地是否存储了该对象的副本,如果有,Web缓存器向客户浏览器用HTTP响应报文返回对象。

3、如果Web缓存器没有该对象,他就会建立一个与该对象的初始服务器的TCP连接。Web缓存器则在这个缓存器到服务器的TCP连接上发送一个对该对象的HTTP请求。在收到请求后,初始服务器向该Web缓存器发送具有该对象的HTTP响应。

4、当Web缓存器接收到该对象时,他在本地存储空间存储一份副本,并向客户的浏览器用HTTP响应报文发送该副本(通过现有的客户浏览器和Web缓存器之间的TCP连接)。

注意web缓存器是服务器同时又是客户。当他接收到浏览器的请求并发送响应时,他是服务器。当他向初始服务器发出请求并接受响应时,他是一个客户。

为什么我们要在因特网上部署Web缓存器?首先,Web缓存器可以大大减少客户对请对的响应时间,特别时当客户与初始服务器之间的瓶颈带宽远低于客户与Web缓存器之间的瓶颈带宽时。其次Web缓存器可以大大减少一个机构的接入链路到因特网的通信量。通过减少通信量,该机构就不必急于增加带宽,因此降低了费用。

为更好理解,我们举一个例子:下图网络环境下,机构网络是一个高速的局域网,它的一台路由器与因特网上的一台路由器通过一条15Mpbs的链路连接。这些初始服务器与因特网相连于全世界各地。假设对象的平均长度为1Mb,从机构内的浏览器对这些初始服务器的平均访问速率为每秒15个请求。假设HTTP请求报文小到可以忽略,因而不会在网络中以及接入链路上产生什么通信量。我们还假设从因特网接入链路一侧的路由器转发HTTP请求报文开始,到他收到其响应报文为止的时间平均为2s.我们非正式的将该持续时延称为“因特网时延”。

总的响应时间,即从浏览器请求一个对象到介接受到该对象为止的时间,是局域网时延、接入时延和因特网时延之和。我们粗略计算一下这个时延。局域网上的流量强度为:

(15个请求/s) * (1Mb/请求) / (100Mbps) = 0.15

然而接入链路上的流量强度为:

(15个请求/s) * (1Mb/请求) / (15Mbps) = 1

局域网上强度为0.15的通信量最多导致数十毫秒的时延,因此我们可以忽略局域网时延。然而如果流量强度接近1,链路上的时延会变得非常大并且无限增长。因此,满足请求的平均响应时间将在分钟的量级上。然而必须想办法来改进时间响应特性。

一个可能的解决方法就是增加接入链路的速率,如从15Mbps增加到100Mbps。这可以将接入链路的流量减少到0.15,这样一来,两台路由器之间的链路时延可以忽略了。这时,总的响应时间大约为2s,即为因特网时延。但这种解决方案也意味着该机构必须将他的接入链路由15Mbps升级为100Mbps,这是一种代价很高的方案。

现考虑另一种解决方案,即不升级链路带宽而是在机构网络中安装一个Web缓存器。实践中的命中率(即由一个缓存器所满足的请求比率)通常在00.2~0.7之间(可以理解为每10个请求就有2~7个是Web缓存器可以满足的)。我们假设命中率为0.4。由于客户和缓存连接在一个相同的高速局域网上,这样40%的请求将几乎立即会由缓存器得到,时延约在10ms内。剩下的60%的请求任然要由初始服务器来满足。但是只有60%的被请求对象通过接入链路,在接入链路上的流量强度从1.0减小到0.6,此时的时延约为几十毫秒,这与2s因特网时延相比是微不足道的。考虑这些后,平均时延为:0.4 * (0.01s) + 0.6 *(2.01s) 略大于1.2s。因此第二种解决方案提供的相应时延比第一种解决方案更低,也不需要该机构升级它到因特网的链路。

 

                                                                                    (上述例子来自《计算机网络——自顶向下》)

条件GET方法

高速缓存可以减少用户响应时间,但是由于高速缓存只能存储某一时刻的对象的备份,如果该对象在初始服务器内更新了,Web缓存器是不会更新的。也就是说如果你今天请求一篇新闻的网页,第二天继续向Web缓存器请求访问这个新闻网页,那么你所看到的已经是“历史”了。

HTTP协议有一种机制,允许缓存器证实它的对象是最新的。这种机制就是条件GET(conditional GET)方法。如果1.请求报文使用GET方法;2.请求报文中包含一个“If-Modified-Since:”首部行。那么这个HTTP请求报文就是一个条件GET请求报文。

如果一个代理缓存器代表一个请求浏览器,向某Web服务器发送一个请求报文:

GET /fruit/Kiwi.gif HTTP/1.1
Host: www.exotiquecuisine.com

其次,该Web服务器向缓存器发送具有被请求的对象的响应报文

HTTP/1.1 200 OK
Date: Sat, 8 Oct 2011 15:39:29
Server: Apache/1.3.0(Unix)
Last-Modified: Web, 7 Sep 2011 09:23:24
Content-Type: image/gif

(data data data data......)

该缓存器在将对象转发到请求的浏览器的同时,也在本地缓存了该对象。最重要的是,缓存器在存储该对象的同时也存储了最后修改日期。若一段时间之后一个用户经过该缓存器请求同一个对象,该对象在缓存器中,但这个对象的状态还是之前的,该对象可以在初始服务器上已经被修改了,因此缓存器要发送一个条件GET执行最新检查。缓存器会发送:

GET /fruit/Kiwi.gif HTTP/1.1
Host: www.exotiquecuisine.com
If-Modified-Since: Web, 7 Sep 2011 09:23:24

首部行的If-Modified-Since:值是缓存器最近一次获取到该对象的时间,即缓存器中该对象的最新状态的时间点。若初始服务器上该对象未被修改,则会发送如下响应报文:

HTTP/1.1 304 Not Modified
Date: Sat, 15 Oct 2011 15:39:29
Server:Apache/1.3.0(Unix)

(empty empty empty)

服务器仍会发一个响应报文,但该响应报文并不含有该对象,只是为了告诉缓存器304 Not Modified。然后缓存器就确认了该对象是最新的,就可以向客户浏览器发送它缓存的该对象的副本。

黄大牙牙yyds

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值