从本文你将看到:HTTP是干嘛用的?怎样和服务器通信?HTTP的基本性质?HTTP能控制什么?基于HTTP三大组件系统?HTTP 和 TCP 之间的关系?HTTP 协议如何使用 TCP 连接? 本文没什么高深的东西,就是把一些概念整理了一下,大牛可以飘过,不喜勿喷 ## 一、什么是HTTP **HTTP是干嘛用的?** HTTP学名叫做超文本传输协议,是一个网络协议。 是专门用来帮你传输诸如 HTML 的超媒体文档等 Web 内容滴。因为 HTML 本身就是超文本标记语言,HTML 中不仅有文本还有图片、音视频等内容,所以用来传输它的协议当然就叫超文本传输协议了。 比如你访问俺的博客的主页,浏览器地址栏会出现如下的网址:**http**://dunizb.com/,加了粗体的部分就是指 HTTP 协议。大部分网站都是通过 HTTP 协议来传输 Web 页面、以及 Web 页面上包含的各种东东(图片、CSS 样式、JS 脚本)。 它基于 TCP/IP 的应用层协议。它被设计用于Web浏览器和Web服务器之间的通信,但它也可以用于其他目的。 它是 Web 上数据交换的基础,是一种 client-server 协议,也就是说请求通常是由像浏览器这样的接受方发起的。一个完整的 web文档是由不同的子文档重新组建而成的,像是文本、布局描述、图片、视频、脚本等等。 **怎样和服务器通信?** 1. HTTP遵循经典的客户端-服务端模型,客户端打开一个连接以发出请求,然后等待它收到服务器端响应。 HTTP是无状态协议,意味着服务器不会在两个请求之间保留任何数据(状态)。 2. 客户端和服务端通过交换各自的消息(与数据流正好相反)来进行交互。通常由像浏览器这样的客户端发出的消息叫做 requests,那么被服务端回应的消息就叫做 responses。 HTTP 被设计于上20世纪90年代初期,**是一种可扩展性的协议。它是应用层的协议**,虽然理论上它可以通过任何可靠的传输协议来发送,但是它还是通过 TCP,或者是 TLS-加密的TCP连接来发送。因为它很好的扩展性,时至今日它不仅被用来传输超文本文档,还用来传输图片、视频或者向服务器发送如 HTML 表单这样的信息。HTTP 还可以根据网页需求,来获取部分web文档的内容来更新网页。 HTTP遵循经典的[客户端-服务端模型](https://en.wikipedia.org/wiki/Client%E2%80%93server_model),客户端打开一个连接以发出请求,然后等待它收到服务器端响应。 HTTP是[无状态协议](http://en.wikipedia.org/wiki/Stateless_protocol),意味着服务器不会在两个请求之间保留任何数据(状态)。虽然通常基于TCP / IP层,但可以在任何可靠的[传输层](https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E5%B1%82)上使用;也就是说,一个不会静默丢失消息的协议,如UDP。 ## 二、HTTP的基本性质 总述:HTTP是简单的、可扩展、无状态的 **HTTP 是简单的** 即便在HTTP/2中把HTTP消息封装到了frames中,HTTP大体上还是被设计成可读的而且简单的。HTTP的消息能够让人读懂且明白它的意思,还允许简单的测试,放低了门槛,更有利于新来者了解。 **HTTP 是可扩展的** 在HTTP/1中就出现了, HTTP headers 让协议扩展变得非常容易。只要服务端和客户端在新的headers上语义达成一致,新的功能就可以轻松地被加进来。 **HTTP 是无状态,有会话的** HTTP是无状态的:在同一个连接中,两个成功执行的请求之间是没有关系的。这就带来了一个问题,用户没办法在一个网站进行连续的交互,比如在一个电商网站里,用户把某个商品加入了购物车中,换了一个页面后再次添加商品,两次添加商品的请求没有联系,浏览器无法知道最终用户都选择了哪些商品。而用HTTP的头部扩展,**HTTP Cookies就可以解决这个问题**(将在后面介绍)。把Cookies添加到头部中,创建一个会话来让每次请求都能共享相同的上下文信息,相同的状态。**而HTTP的核心是无状态的,cookies的使用可以创建有状态的会话。** ## 三、HTTP能控制什么 多年以来,HTTP良好的扩展性控制着越来越多Web的功能。缓存和认证方式很早就可以由HTTP来控制了。另一方面,对同源同域的限制到2010年才有所改变。 下面就是可以用HTTP来控制的常见特性。 **缓存** 文档怎么缓存能够通过HTTP来控制。服务端能告诉代理和客户端什么需要被缓存,缓存多久,而客户端能够根据请求条件首部字段(如If-Modified-Since、If-Match等)来忽略存储的文档。 **开放同源限制** 为了防止网络窥听和其它的隐私泄漏,浏览器强制对Web网站做了分割限制。只有来自于相同来源的网页才能够获取网站的全部信息。这样的限制有时反而成了负担,HTTP可以通过修改头部来开放这样的限制,因此web文档可以是由不同域下的信息拼接成的(在某些情况下,这样做还有安全因素考虑在里面)。 **认证** 一些页面能够被保护起来,仅让特定的用户进行访问。基本的认证功能可以直接通过HTTP提供,使用Authenticate相似的头部就可以,或者用HTTP cookies来设定指定的会话。 **代理和隧道** 通常情况下,服务器和/或客户端是处于内网的,对其它(外网)隐藏其真实 IP 地址。因此 HTTP 请求就要通过代理越过这个网络屏障。但并非所有的代理都是 HTTP 代理。例如,SOCKS协议的代理就运作在更底层。一些像 ftp 其它的协议也能够被它们处理。 **Cookies** Cookies用一个服务端的状态连接起了每一个请求。这就创建了会话,虽然基本的HTTP是无状态协议。这很有用,不仅是因为能用到购物车这样的电商业务上,更是因为,它使得任何网站都能够配置页面展现的东西了。 ## 四、基于HTTP三大组件系统 **客户端:user-agent** 严格意义来说,user-agent 就是任何能够为用户发起行为的工具。但实际上,这个角色通常都是由浏览器来扮演。对于发起请求来说,浏览器总是作为发起一个请求的实体,而永远不是服务器(虽然一些机制已经能够模拟服务器发起请求的消息了)。 **Web服务端** 在上述通信过程的另一端,就是一个Web Server来服务并提供客户端请求的文档。Server只是虚拟意义上:它可以是许多共同分担负载(负载平衡)的一组服务器组成的计算机群,也可以是一种复杂的软件,通过向其他计算机发起请求来获取部分或全部资源的软件。 Server不再只是一个单独的机器,它可以是在同一个机器上装载的许多服务之一。在HTTP/1.1和Host头部中,它们甚至可以共享同一个IP地址。 **Proxies 代理** 在浏览器和服务器之间,有许多计算机和其他设备转发了HTTP的消息。因为Web栈层次结构的原因,它们大多数都出现在传输层、网络层和物理层上,对于HTTP的应用层来说就是透明的(虽然它们可能会对应用层的性能有重要影响)。而还有一部分表现在应用层上的,就叫做proxies了。Proxies既可以表现得透明,又可以不透明(看请求是否通过它们),主要表现在这几个功能上: * 缓存(可以是公开的或是私有的,像浏览器的缓存) * 过滤(像反病毒扫描,家长监护) * 负载均衡,让多个服务器服务不同的请求 * 对不同资源的权限控制 * 登陆,允许存储历史信息 每一个发送到服务器的请求,都会被服务器处理并且返回一个消息,也就是response。在client与server之间,还有许许多多的被称为proxies的实体,他们的作用与表现各不相同,比如有些是网关,还有些是caches等。 ![](https://segmentfault.com/img/remote/1460000012368736?w=819&h=121) 实际上,在一个浏览器和处理请求的服务器之间,还有计算机、路由器、调制解调器等等许多实体。由于Web的层次设计,那些在网络层和传输层都不可见了。HTTP是在最上层应用层中的,虽然下面的层次对分析网络问题非常重要,但是对HTTP的描述来说,这些大多数都是不相关的。 ## 五、HTTP 和 TCP 之间的关系 前面说过,HTTP是基于 TCP/IP 的,简单地说,TCP 协议是 HTTP 协议的基石——HTTP 协议需要依靠 TCP 协议来传输数据。 在网络分层模型中,TCP 被称为“传输层协议”,而 HTTP 被称为“应用层协议”。有很多常见的应用层协议是以 TCP 为基础的,比如“FTP、SMTP、POP、IMAP”等。 TCP 被称为“面向连接”的传输层协议。关于它的具体细节,俺就不展开了(否则篇幅又失控了)。你只需知道:传输层主要有两个协议,分别是 TCP 和 UDP。TCP 比 UDP 更可靠。你可以把 TCP 协议想象成某个水管,发送端这头进水,接收端那头就出水。并且 TCP 协议能够确保,先发送的数据先到达(与之相反,UDP 不保证这点)。 ## 六、HTTP 协议如何使用 TCP 连接? HTTP 对 TCP 连接的使用,分为两种方式:俗称“短连接”和“长连接”(“长连接”又称“持久连接”,洋文叫做“Keep-Alive”或“Persistent Connection”) 假设有一个网页,里面包含好多图片,还包含好多 外部的 CSS 文件和 JS 文件。在“短连接”的模式下,浏览器会先发起一个 TCP 连接,拿到该网页的 HTML 源代码(拿到 HTML 之后,这个 TCP 连接就关闭了)。然后,浏览器开始分析这个网页的源码,知道这个页面包含很多外部资源(图片、CSS、JS)。然后针对 每一个 外部资源,再分别发起一个个 TCP 连接,把这些文件获取到本地(同样的,每抓取一个外部资源后,相应的 TCP 就断开) 相反,如果是“长连接”的方式,浏览器也会先发起一个 TCP 连接去抓取页面。但是抓取页面之后,该 TCP 连接并不会立即关闭,而是暂时先保持着(所谓的“Keep-Alive”)。然后浏览器分析 HTML 源码之后,发现有很多外部资源,就用刚才那个 TCP 连接去抓取此页面的外部资源。 在 HTTP 1.0 版本,默认使用的是“短连接”(那时候是 Web 诞生初期,网页相对简单,“短连接”的问题不大). 到了1995年底开始制定 HTTP 1.1 草案的时候,网页已经开始变得复杂(网页内的图片、脚本越来越多了)。这时候再用短连接的方式,效率太低下了(因为建立 TCP 连接是有“时间成本”和“CPU 成本”滴)。所以,在 HTTP 1.1 中,默认采用的是“Keep-Alive”的方式。 ## 七、一些术语 **资源(resource)** Web资源是使用URL指向的Web内容。 * 内容可以是静态的,如:文本文件、HTML文件、JPEG文件。 * 或者是动态的内容。如:摄像头的实时采集软件生成的动态影像,用户填写的电子网站订单。 **资源类型** Web服务器会为所有HTTP资源赋予一个类型,以便于HTTP软件处理消息主体。如,用 text/html 标记 html。可以再看两个案例: * text/plain :ASCII文本文档 * image/jpeg :JPEG版本的图片 非常多的资源类型和文本标记的对应关系,一起构成了一个超长的清单,并且由RFC 2045标准化。此标准被称为MIME。MIME是Multipurpose Internet Mail Extension的缩写。虽然名称很长,但是含义简单,就是用来指定消息内的实体类型的。之所以有Mail字样,是因为最初设计是为了Mail的异构系统交换文档的。 **资源标示符** URL是一种资源位置标示方法。URL描述了一个资源在服务器上的位置。这就是一个合法的URL:[http://example.com/part/index...](http://example.com/part/index.htm)。 * 第一部分:方案(scheme)。指明了访问资源所使用的协议类型。这部分通常是HTTP协议([http://)](http://%29/)。 * 第二部分:服务器地址(比如,example.com)。 * 其余部分指定了Web服务器上的某个资源(比如,/part/index.htm)。 当在地址栏输入此资源名并回车后,用户代理会把URL解析,把必要的信息以HTTP协议的要求,打入请求消息内。以[http://www.example.com/index....](http://www.example.com/index.html),变成 ~~~ GET index.html HTTP/1.1 host:www.example.com 空行 ~~~ 打开到www.example.com的tcp连接,并发送此请求消息给服务器,然后等待服务器响应并解析显示给用户。 > 更多URL、URI、URN详细推荐阅读:[《你知道URL、URI和URN三者之间的区别吗?》](http://web.jobbole.com/83452/) **HTTP事务** 一个HTTP事务由一条请求消息和一个响应消息构成。 **HTTP方法** HTTP支持几种不同的请求命令,这些命令被称为HTTP方法(HTTP method)。每条HTTP请求报文都包含一个方法。 **状态码** 每条HTTP响应消息返回时都会携带一个状态码。状态码是一个三位数字的代码,告知客户端请求是否成功,或者是需要采取其他行动。 **消息** 从Web客户端发往Web服务器的HTTP报文称为请求消息。从服务器发往客户端的消息称为响应消息。HTTP报文包括三部分: ~~~ 起始行 首部字段 主体 ~~~ 如发送一个hello.htm 的资源给客户端,请求消息是: ~~~ GET /hello.html HTTP/1.1 ~~~ 请求消息只有起始行,指明使用的HTTP方法、资源的URL,以及协议的版本。没有首部字段和主体。 响应消息为: ~~~ HTTP/1.1 200 OK X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 22 ETag: W/"16-FmHX0hamHjYkHeAP/7PfzA" Date: Thu, 03 Dec 2015 09:54:01 GMT Connection: close <h1>Hello, World!</h1> ~~~ 这个消息第一行为起始行,指明协议版本、状态码(200表示成功)和状态说明(OK)。接下来一直到空行之间都是首部字段,用来说明服务器、资源类型、内容长度、生成文档时间等。空行后就是主体,这里就是一个html文件的内容。实际上,主体可以承载任何内容,而不限于文本。 ## 总结 HTTP是一个简单快速、灵活、无连接、无状态的超文本传输协议。 HTTP是很简单可扩展的一种协议。结合了轻松添加头部信息能力的Client-server结构使得HTTP可以和Web的功能扩充一同发展。 即使HTTP/2为了提高性能把HTTP报文嵌到帧中这一举措增加了复杂度,但是从Web应用的角度来看,报文的基本结构是没有变化的,从HTTP/1.0发布起就是相同的。 * * * 关于HTTP,如果你不想啃大部头的《HTTP权威指南》,那么强烈建议你阅读刘传君的图灵电子书《HTTP小书》,准能帮你节省不少时间,只要9块钱!戳这里:[http://www.ituring.com.cn/book/1791](http://www.ituring.com.cn/book/1791)