HTTP协议详解
- HTTP运行机制
HTTP 协议基于请求 / 响应(Request / Response)模式实现,相当于客户 / 服务器模式。它为客户 / 服务器通信提供了握手方式及报文传送格式,支持客户端(浏览器)与服务器之前的通信
- 客户端首先要与服务器建立 TCP 连接
- 客户端向服务器发送 HTTP 请求报文(请求方法、URI 统一资源标识符)和协议版本号,以及一个类 MIME 消息,类 MIME 消息又包括请求修饰符、客户端信息和可能的报文主体内容
- 服务器向客户端发送 HTTP 响应报文(状态行和一个类 MIME 消息),状态行包含报文的协议版本和成功、出错的状态码,类 MIME 消息包含服务器信息、实体元信息,以及可能的实体内容
- 关闭 HTTP 连接,当 HTTP 服务器响应了客户端的请求之后便关闭连接,直到下一个请求才重新建立连接。如果客户端支持 HTTP 1.0 且能够保持激活的 HTTP,则客户端将维持这个连接,而不是创建另一个新的会话。如果客户端与服务器任何一方关闭连接,不管事务处理成功与否以及完成与否,都将关闭连接。
- HTTP 通信方式
- 点对点 HTTP 通信方式,大部分的 HTTP 通信是由用户代理发起的,由应用到源服务器上一个资源的请求组成。
- HTTP 通信方式更复杂的情形是在请求 / 响应链中出现一个或多个中间系统。常见的蹭系统有代理、网关和隧道3种类型。作为一种转发代理,代理接收绝对 URI 请求,重写全部或部分报文,然后将格式化的请求发送到 URI 所指定的服务器。网关是一种接收代理(receiving agent),相当于服务器之上的一个层,必要时它会将请求转换成下层服务器的协议。隧道不改变报文而充当两个连接之间的中继点,当通信需要穿越中间系统(如防火墙),甚至当中间系统不能理解报文内容时,可以使用隧道。
- 缓存(Cache),任何非隧道的通信成员都可能会采用一个内部缓存来处理请求。如果沿着链的通信成员对请求采用了缓存响应,请求 / 响应链就会大大缩短。缓存方式的一个最终请求响应链,假定其中中间系统 B 拥有一个来源服务器的以前请求过的响应副本,但此响应尚未被用户代理或中间系统 A 缓存。
- HTTP 协议的主要特点
- HTTP 是一种非常简单的协议,这就使得 HTTP 服务器程序规模小,与其他协议相比时间开销较少。它的通信速度很快,可以有效地处理大量请求,因而得到了广泛的使用。在客户端与服务器连接后,HTTP 协议要求客户端必须传送的信息只是请求方法和路径。
- HTTP 是一种无连接协议。每次连接只处理一个请求,并且客户端接到服务器响应后立即断开连接。使用无连接协议,如果客户端没有发出请求,服务器不会专门等待,也不会在完成一个请求后还保持原来的请求,而是会立即断开这次连接。与保持连接协议相比,无连接协议即使服务器实现变得比较简单,又能充分利用网上的资源。
- HTTP 是一种无状态的协议。这种无状态使客户端与服务器连接通信运行速度快,服务器响应也快。但是,无状态协议对事务处理没有记忆,为满足后续事务处理需要前面事务的有关信息的需要,有关信息必须在协议外面保存,这导致每次连接要传送较多的信息。
- HTTP 是基于元数据的协议。HTTP协议对所有事务处理都加了首部,即在主要数据前面加一部分信息,称之为元数据,即关于信息的数据。用户可以利用元数据进行有条件的请求,或者报告一次事务处理是否成功等。
- HTTP 报文
HTTP 报文采用 RFC 822定义的通用报文格式,由起始行(start-line)、报文首部(message-header)、一个指示报文首部结束的空行和一个可选的报文主体(message-body)构成。这种报文格式用于传输实体(报文的负载)。
- HTTP 请求
1.请求行:以一个方法标记开始,后面跟随请求 URI (Request-URI)和协议版本,最后以CRLF(回车 / 换行)对结束。这部分以 SP (空格)字符分隔。
方法 | SP | 请求 URI | SP | HTTP 版本 | CRLF |
2.方法:指请求 URI 指定的资源上执行的方法,在请求行中方法标记本身区分大小写
方法 | 说明 |
GET | 获取由请求 URI 指定的信息。如果请示 URI 涉及一个数据生成过程,那么这个生成的数据应该被作为实体在响应中返回,但这并不是过程的资源文本,除非资源文本恰好是过程的输出 |
HEAD | HEAD 与 GET 一致,除了服务器不能在响应中返回报文主体。HEAD 请求响应中 HTTP 首部字段中的元信息应该与 GET 请求响应中的元信息一致。此方法经常用来测试超文本链接的有效性、可访问性以及最近的改变 |
PUT | 请求服务器将包含的实体存储在请求 URI 所指示的资源中。如果请求 URI 指定的资源已经在源服务器上存在,那么此请求的实体应该被当作修改版本。如果请求 URI 指定的资源不存在,并且此 URI 被用户代理定义为一个新资源,那么源服务器就应该根据请求里的实体创建一个新的资源 |
DELETE | 请求源服务器删除请求 URI 指定的资源 |
TRACE | 用于激发一个远程的、应用层的请求报文回送也就是将到达的请求回送给客户端。该方法用来确保 HTTP 服务器所接收到的数据是正确的。TRACE 的响应是实际的 HTTP 请求,允许对 HTTP 请求进行测试和调试 |
CONNECT | 保留给 SSL 隧道使用 |
OPTIONS | 表示请求由 URI 指定的请求响应链上可得到的通信选项信息。此方法允许客户端去判定请求资源的选项或需求,或服务器的能力,而不需要进行资源操作 |
3.请求URI (Request-URI)
GET /pub/WWW/TheProject.html HTTP/1.1
Host:http://www.w3.org/
3.请求首部字段(Request Header Fields)
请求首部字段只能出现在请求报文中,作为请求的修饰符,允许客户端传递的附加信息和客户端自己的附加信息给服务器。
首部字段 | 含义 |
Accept | 客户端能够接受的媒体格式 |
Accept-chart | 客户端能够处理的字符集 |
Accept-encoing | 客户端能够处理的编码方案 |
Accept-language | 客户端能够接受的语言 |
Authorization | 客户端具有何种准许 |
From | 用户的电子邮件地址 |
Host | 客户端的主机和端口号 |
If-modified-since | 只有当指明日期更新时发发送这个文档 |
If-match | 只有当与给定标记匹配时才发送这个文档 |
If-not-match | 只有当与给定标记不匹配时才发送这个文档 |
If-range | 只有发送缺少的那部分文档 |
If-unmodified-since | 若在指明日期之后未改变,则发送文档 |
Referrer | 指明被链接的文档的 URL |
User-went | 标志客户程序 |
- HTTP 响应
收到客户端的 HTTP 请求报文之后,服务器进行处理,然后发出一个 HTTP 响应报文。响应报文的起始行称为状态行,只包含通用首部、响应首部和实体首部。大多数响应报文都带有实体数据。
1.状态行
响应报文的第一行是状态行,由协议版本、数字形式的状态码(Status-Code)和相关的状态描述短语(Reason-Phrase)组成,各部分间用SP(空格)隔开,除了最后的CRLF(回车/换行)外,中间不允许有回车换行。
HTTP 版本 | SP | 状态码 | SP | 状态描述短语 | CRLF |
2.状态码与描述短语
状态码是针对请求的由3位十进制数组成的结果码,其中第1位数字定义了响应的类别,而其他两位数字则与分类无关,是自动形成的。
- 100 ~ 199 表示信息,请求收到继续处理。其中绝大多数未使用,留作将来使用。
- 200 ~ 299 表示成功,服务器对客户端发出请求的接收、理解和处理已成功完成。
- 300 ~ 399 表示重定向,为完成请求所要求采取的操作,客户端需要重新提出请求。
- 400 ~ 499 表示客户端错,请求中有语法错或请求不能被执行。
- 500 ~ 599 表示服务器错,服务器错误地执行一个明显正确的请求。
3.响应首部字段(Response Header Fields)
响应首部字段允许服务器传送响应的附加信息,这些信息不放在状态行里。这些首部字段给出关于服务器和进一步访问由请求 URI 指定的资源的信息。
首部字段 | 说明 |
Accept-Range | 服务器指明它对客户的范围请求 |
Age | 表示发送者对响应(或重验证)在源服务器上产生以来的时间估计 |
Etag | 提供请求对应变量的当前实体标签。实体标签用于比较来自同一资源的不同实体 |
Location | 用于为完成请求或识别一个新资源,使接收者能重定向于由它指示的 URI 而不是请求 URI |
Proxy-Authenticate | 必须包含在 407 响应中,由一个 challenge 和 parameters 组成,challenge 指明谁方案,而 parameters 应用于些请求 URI 的代理 |
Retry-After | 用于一个 503 响应,向请求端指明服务不可得的时长;用于 3XX (重定向)响应,指明用户代理再次提交已重定向请求之前的最小等待时间 |
Server | 包含源服务器用于处理请求的软件信息 |
WWW-Authenticate | 必须包含在 401 响应中,字段值至少应该包含一个指明认证方案的 callenge 各适用于请求 URI 的参数 |
- 持续连接
在版本 1.1 以前的 HTTP 只能实现非持续连接,每一个请求 / 响应都要建立 TCP 连接。
- 客户端打开 TCP 连接并发送请求。
- 服务器发送响应并打开连接。
- 客户端读取数据,直到它遇到文件结束标记,然后关闭连接。
HTTP 1.1 默认的方式是持续连接,服务器在发送响应后,让连接继续为一些请求打开。服务器可以在客户请求时限时到关闭这个连接。这种方式具有以下几个优点:
- 通过建立与关闭较少的 TCP 连接,不公节省路由器与主机的 CPU 时间,还节省了主机用于 TCP 协议控制块的内存。
- 能在连接上进行流水线请求方式,允许客户端执行多次请求而不用等待每一个请求的响应,并且此时只进行一个 TCP 连接,从而效率更高。
- 减少网络阻塞,这是由于 TCP 连接后减少了包的数量,并且允许 TCP 有充分的时间去决定网络阻塞的状态。
- 无需在创建 TCP 连接的握手上耗费时间,而使后续请求的等待时间减少。
- 可以在不需要关闭 TCP 连接的情况下报告错误。