HTTP协议详解

当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, Rails, AJAX 等等。无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了Web应用程序的内部工作。感谢 TankYuan,让繁杂的内容变得简单。

协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器,目前我们使用的是HTTP/1.1 版本。

Web服务器,浏览器, 代理服务器
当我们打开浏览器,在地址栏中输入URL,然后我们就看到了网页。 原理是怎样的呢?
实际上我们输入URL后,我们的浏览器给Web服务器发送了一个Request, Web服务器接到Request后进行处理,生成相应的Response,然后发送给浏览器, 浏览器解析Response中的HTML,这样我们就看到了网页,过程如下图所示:

这里写图片描述

我们的Request有可能是经过了代理服务器,最后才到达Web服务器的。

这里写图片描述

代理服务器就是网络信息的中转站,有什么功能呢?
1. 提高访问速度, 大多数的代理服务器都有缓存功能
2. 突破限制, 比如说防火墙
3. 隐藏身份
当然了,我们的代理服务器也是可以分为正向代理和反向代理的,正向代理是代理客户端,反向代理是代理服务器端。

URL, URI, URN的联系与区别
所有能提供Web内容的东西都是Web资源,包括静态资源和动态资源。URI提供了一种统一的资源命名方式,它标记了资源的访问方式。URI分为URL和URN,一般情况下,URI指的就是URL。

´URL(Uniform Resource Locator) 地址用于描述一个网络上的资源, 基本格式如下:

schema://host[:port#]/path/.../[?query-string][#anchor]
scheme               指定低层使用的协议(例如:http, https, ftp)

host                 HTTP服务器的IP地址或者域名

port#                HTTP服务器的默认端口是80,HTTP的默认端口是443这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/

path                 访问资源的路径

query-string         发送给http服务器的数据

下面来举URL的一个例子

http://www.mywebsite.com/sj/test/test.aspx?name=sviergn&x=true

Schema:                 http
host:                   www.mywebsite.com
path:                   /sj/test/test.aspx
Query String:           name=sviergn&x=true

HTTP协议是无状态的应用层协议
http协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系的,对http服务器来说,它并不知道这两个请求来自同一个客户端。 为了解决这个问题, Web程序引入了Cookie机制来维护状态。我们先来简单回顾一下cookie和session之间的区别,首先session 在服务器端,cookie 在客户端(浏览器)。但他们是相互依存的关系,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了cookie ,同时session也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id) 。

浏览器加载网页需要发送多次Request

  1. 当你在浏览器输入URL http://www.csdn.com 的时候,浏览器发送一个Request去获取 http://www.csdn.com 的html. 服务器把Response发送回给浏览器

  2. 浏览器分析Response中的 HTML,发现其中引用了很多其他文件,比如图片,CSS文件,JS文件

  3. 浏览器会自动再次发送Request去获取图片,CSS文件,或者JS文件

  4. 等所有的文件都下载成功后。 网页就被显示出来了

HTTP报文
好的,经过这么多铺垫,我们终于来到这篇博中重要的环节。
在计算机网络中,我们一般将应用层要发送的数据称为报文。报文是来自客户端的请求数据或者是来自服务端的响应数据。HTTP报文是基于文本行的格式化数据,尽管这对计算机来说可能不够友好(影响效率又容易出错),可是这也增加了HTTP的可扩展性和可调试性(当我们拿到一条报文时不必去查找二进制与实际意义的对应关系)。这样还是有些好处的。

HTTP报文由三个部分组成:一个对报文进行描述的起始行(start line),零个或多个说明属性的首部(header),以及可选的、包含数据的实体主体(entity-body,实体的主体部分)。

HTTP请求报文(request message)的语法如下:

<method> <request-uri> <HTTP-version>
<headers>
<entity-body>

HTTP响应报文(response message)的语法如下:

<HTTP-version> <status-code> <reason-phrase>
<headers>
<entity-body>

方法 :method
指明了将要以何种方式来访问由请求URI指定的资源,方法是大小写敏感的
请求URI :request-uri
包含资源绝对路径的URL,服务器可以假定自己是URL的主机/端口
HTTP版本:HTTP-version
包含HTTP版本的主版本号和次要版本号,如HTTP/0.9,HTTP/1.1等。版本号是为了让通信双方了解彼此的能力
状态码:status-code
由三位数字组成,表明了请求是否被理解或被满足,描述了请求过程中发生的情况
原因短语:reason-phrase
用简短的文字来描述状态代码产生的原因。原因短语不做特殊限制,通常使用通用的描述方便交流,客户端不需要检查或显示原因短语。
首部:headers
可以有零个或多个首部,每个首部包含一个名字,后面跟着一个冒号(:),然后是一个可选的空格,接着是一个值,最后是一个。首部描述了请求或者响应的一些属性,有些HTTP版本要求报文中必须包含某些特定的首部。
实体主体:entity-body
包含一个由任意数据组成的数据块,并不是所有的报文都包含实体主体,由请求方法与响应状态码决定

还需要注意的是,起始行和首部都是纯文本的,但实体主体没有此限制

请求报文的例子,可以有零个或者多个首部:

GET /example.html HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8

还有一个响应报文的例子:

HTTP/1.1 200 OK
Date: Sun, 16 Apr 2017 01:40:46 GMT
Server: Apache/2.4.23 (Win64) PHP/5.6.24
Last-Modified: Sun, 16 Apr 2017 01:40:01 GMT
ETag: "8a-54d3ec0d24918"
Accept-Ranges: bytes
Content-Length: 138
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

<!DOCTYPE html>
<html>
  <head>
    <title>EXAMPLE</title>
  </head>
  <body>
    <p>Hello, This is an example page.</p>
  </body>
</html>

HTTP报文解析
1. 协议版本
HTTP的第一个版本是HTTP/0.9,协议内容非常简单:请求报文只有一个请求行且没有版本描述,响应报文只有实体主体。HTTP/0.9只支持GET方法,而且服务器只能回应HTML格式的字符串,不能回应别的格式。定义它的初衷只是为了获取简单的HTML对象。很快它就被HTTP/1.0取代了。

HTTP/1.0是第一个得到广泛使用的HTTP版本,它于1996年5月发布,定义于rfc1945当中。协议的内容大大增加,添加了版本号、首部、一些额外的方法以及服务器响应的状态码。HTTP/1.0引入了POST方法和HEAD方法,而且任何格式的内容都可以发送了。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。HTTP/1.0的新特性使得HTTP的可用性大大提高,为了满足商业需要,各个Web客户端和服务器厂商都在向HTTP中添加各种新特性,于是产生了一个HTTP的非正式扩展版本,已经成为非官方的事实标准,通常称之为HTTP/1.0+。

HTTP/1.1对HTTP/1.0+进行改进,主要关注的是设计中的缺陷与语义明确,引入了一些性能优化措施,并删除了一些不好的特性。HTTP/1.1最初于1997年1月发布,定义于rfc2068中,后来又在1999年6月重新修订,形成了现在广为人知的rfc2616。

HTTP/2已经在2015年5月发布了草案,定义于rfc7540。这个版本删除了次要版本号,所以你看到的是HTTP/2而不是HTTP/2.0。这个版本将HTTP的语义进行了优化,比如采用了二进制描述。
2. 方法
方法除了HTTP协议预定义的一些请求方法外是可以扩展的,下表列出的方法被大多数商业服务器所实现。

方法描述是否包含实体起始版本
GET从服务器获取一份文档HTTP/0.9
HEAD向服务器获取以GET方法请求时文档的首部HTTP/1.0
POST向服务器发送要处理的数据HTTP/1.0
TRACE对可能经过代理服务器的报文进行跟踪HTTP/1.1
OPTIONS了解服务器可以对资源执行哪些方法HTTP/1.1

并不是所有的服务器都实现了所有方法。如果服务器不理解客户端发送的方法,就会返回501或者405的状态码。

HTTP将不会在服务器上产生任何结果的方法称为安全方法(这里的产生结果是指修改数据),GET和HEAD被设计为安全方法。实际上安全方法并非真的不会产生结果,这取决于Web开发者。安全方法被设计的目的在于提示/通知用户不安全的方法可能会导致一些后果(比如点击支付按钮的可能导致账户扣款)。
3. 状态码
方法告诉服务器做什么事情,状态码则告诉客户端发生了什么事情。状态码由三位数字组成,根据第一位数字分成五大类:

  • 1xx:信息型状态码
  • 2xx:成功状态码
  • 3xx:重定向状态码
  • 4xx:客户端错误状态码
  • 5xx:服务端错误状态码

原因短语通常和状态码一起使用,但原因短语是给人看的,比如,对客户端或服务器来说,它对200 OK和200 Done的处理方式完全一样。尽管如此,大多数服务器还是会返回HTTP协议推荐的原因短语。

状态码原因短语含义
200OK成功请求,实体包含所请求的资源
304Not Modified客户端发起条件GET请求,同时所请求资源未修改就返回这个状态码,表明可以使用缓存。返回这个状态码时不应该包含实体主体
400Bad Request告知客户端发了一个错误的请求
403Forbidden服务器拒绝请求,返回实体可能说明拒绝原因,但这个状态码通常是在服务器不想说明拒绝原因的时候使用的
404Not Found请求资源不存在
414Request URI Too Large请求的URI太长,超过服务器能处理的范围
500Internal Server Error服务器遇到了一个妨碍完成请求的错误
502Bad Gateway作为代理或网关的服务器收到了错误响应时使用此状态码**

4. 首部
首部和方法、响应码配合工作,来决定客户端和服务器能做什么事情。首部可以分为五个主要类型。

通用首部:客户端和服务器都可以使用的首部。
请求首部:请求报文特有的首部
响应首部:响应报文特有的首部
实体首部:对应于实体的主体部分的首部
扩展首部:由应用程序开发者创建的非标准首部

类别首部含义
通用首部Date提供日期和时间,说明报文的创建时间
通用首部Cache-Control用于控制缓存
请求首部Host说明所请求的服务器主机
请求首部If-Modified-Since只有在指定日期后资源被修改过才完成这个请求,否则返回304
响应首部Server服务器应用程序软件的名称和版本
实体首部Content-Length说明实体主体的长度
实体首部Content-Type说明实体的MIME类型
实体首部Last-Modified说明实体的最后一次修改日期和时间

HTTP事务
HTTP协议是应用层的通信协议,它依赖传输层的TCP协议来完成报文的发送与接收。TCP协议是面向字节流的可靠的传输层协议,它可以保证数据无误的从发送端到达接收端,因此我们在使用HTTP协议的时候,无需考虑报文是否被正确传输,这些事情TCP都帮我们做了。

HTTPS协议是基于SSL/TLS的HTTP协议。抽象的看,HTTPS主要是在TCP和HTTP之间加了一层“安全层”(确切来说应该是OSI中的表示层和会话层)利用SSL/TLS来对数据进行加密解密。下一篇博文我们就介绍一下HTTPS的原理。

                                  +-------------------+
                                    |        HTTP       |
+-------------------+               |-------------------|
|        HTTP       |               |     SSL or TLS    |  安全层
|-------------------|               |-------------------|
|        TCP        |               |        TCP        |
|-------------------|               |-------------------|
|         IP        |               |         IP        |
|-------------------|               |-------------------|
| Network Interface |               | Network Interface |
+-------------------+               +-------------------+
      HTTP协议栈                           HTTPS协议栈

HTTP在传输数据前,先建立TCP连接,连接建立好后就在客户端和服务器间形成了一条虚拟电路,HTTP报文可以沿着这条虚拟电路到达指定位置,报文发送完毕可以根据具体情况决定是否需要关闭连接。

关于TCP的信息这里不做过多阐述,我们重点关注HTTP的工作过程。

我们将一条客户端发送到服务器的请求报文与服务器返回给客户端的响应报文合起来称为一个HTTP事务。 最初一个TCP连接仅处理一个HTTP事务。后来为了优化性能提出了持久连接的概念。尽管如此,我们仍需知道HTTP协议是无状态的,也就是说在多个HTTP事务中,每个事务都是独立的,无论TCP连接是持久的还是完成一个事务就断开,HTTP都不会记录此事务的连接状态(对比FTP,FTP在进行用户认证后会一直保持和这个用户的会话,直至关闭连接,但HTTP不会)。

一个HTTP事务的处理过程举例:
1. 客户端从URL中解析出服务器的主机名 ,DNS域名解析
2. 客户端将服务器主机名转化为IP地址
3. 客户端从URL中解析出端口号(如果有)
4. 客户端建立与服务器的TCP连接
5. 客户端向服务器发送一条HTTP请求报文
6. 服务器处理客户端发送的请求,生成响应报文发回客户端
7. 客户端收到响应报文,关闭连接

HTTP中长链接和短链接

在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等,每遇到这样一个Web资源,就会建立一个HTTP会话。

从HTTP/1.1起,默认使用的是长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入:Connection:keep-alive。在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值