网络协议(一)HTTP协议(上)

HTTP

  对于HTTP协议,咱们或多或少都知道它是HyperText Transfer Protocol,也就是所谓的超文本传输协议,但其实它里面有不少能够深究的地方。html

  在了解HTTP以前,咱们须要知道一件事,HTTP协议实际上咱们随处可见,甚至说,咱们如今所处的网络下底层运转就是靠HTTP来运转的。python

  那么提到HTTP,咱们就得提到万维网之父蒂姆·伯纳斯·李,是他提出了在互联网上构建超文本系统,也就是将超文本技术应用到计算机当中。后来,万维网和HTTP就所以而诞生了。这中间的过程在这里不过多阐述,网络上或者书本上都有相关介绍。在这之中他也提出了三个概念:URI、HTML以及HTTP。web

  接下来咱们先来了解一下HTTP的发展历程。算法

 HTTP的发展历程

   在最先期的时候,HTTP尚未版本号,咱们所熟知的HTTP1.0/1.1都是后续添加的版本号。而实际上在1.0以前,还有一个版本号HTTP/0.9。编程

   HTTP/0.9呢,它在响应格式上是纯文本形式的,而且也就只有“GET”这个方式去获取HTML的内容,是一个受限于时代发展的版本。然后来随着计算机多媒体技术的发展,HTTP协议也顺势进化,就出现了HTTP/1.0版本。浏览器

   在HTTP/1.0版本,向响应中加入了响应状态码。而且除了原有的GET方式之外,又增长了POST等方式。还有咱们耳熟能详的Header,也是在这个版本中诞生的。在HTTP/1.0正处于热火状态的时候,发生了著名的网景与微软的浏览器大战,又再次推进了HTTP协议的发展,至此HTTP/1.1版本就诞生了。缓存

   那么HTTP/1.1版本中又有什么变更呢?最主要的几个变更以下:增长了缓存管理、链接管理、对响应数据进一步分块等等。安全

   咱们必需要说的就是这个HTTP/1.1版本,它其实是对HTTP/1.0维护,但它具备HTTP/1.0版本没有的意义,那就是HTTP/1.1是一个标准,铁则。这是什么意思呢?就是只要互联网用到HTTP协议,咱们就得遵照HTTP/1.1版本的规矩,好比浏览器、服务器以及代理等。服务器

   在当时HTTP/1.1版本已经够用了,可是随着互联网的发展,HTTP/1.1版本已经有点力不从心了,后来谷歌就在这之中开发了Chrome浏览器,而且提出了一个新协议SPDY。而这个SPDY协议呢,就是HTTP/2的前身,或者说是HTTP/2的基底。网络

   在HTTP/2中对性能作了很大的提高,好比说将协议改成了二进制协议,新设计的压缩算法等。对于HTTP/2,其实是对语义,语法进行了必定的划分。可是谷歌并不知足,它又提出了一个新的协议叫gQUIC,而且在前几年成功的成为了HTTP/3的前身。

   而关于HTTP3的RFC尚未正式出版,但能够先知道它是一个基于UDP的多路复用以及安全传输协议。

  对于HTTP的发展历史,若是有更多的兴趣能够再去详细了解,这里只对它进行一个概述。那么,当咱们了解完HTTP的发展历程之后,咱们就能够步入正题:HTTP究竟是什么?

 到底什么是HTTP?

   咱们先来看一下HTTP的全称:HyperText Transfer Protocol,中文翻译过来就是超文本传输协议。

   所谓的“超文本”,就是文字、图片、音频以及视频等的混合“文本”。对于超文本,咱们特别熟悉,好比说HTML,是内部带有各种标签的纯文本样式,是超文本的载体。

   那么再来看“传输”,传输其实特别好理解,就是从A到B或者从B到A,也就是所谓的双向传输,可是不限于AB之间。这是什么意思呢?就是在A和B之间,还能够掺杂着C或者D。换句话来讲,能够有中介,好比咱们所知的CDN、代理等。而实际上在HTTP中“传输”的意义并不在于行为,而在于传输的报文内容

   最后再来看HTTP中最重要的部分:“协议”。何为协议,就是对两个或者两个以上的参与者的行为规范和协商。

   那么其实综合来看,咱们能够获得一个结论:HTTP是一个在计算机中用于规范计算机之间传输数据行为的协议。

   那么咱们知道HTTP是处于应用层的一个协议,在他之下还有其余协议。好比说TCP/IP协议以及SSL/TSL等等,对于这部分的内容,再新开一章讲述。

  在对HTTP剖析以前,咱们须要先了解一些相关的概念。

 相关概念

  DNS

   DNS(Domain Name System),中文名为域名系统

   对于域名,它能够说是IP地址的抽象化,换句话来讲,域名就是物理网卡的MAC进一步抽象化的体现。那么更进一步地说,实际上域名就和编程中的变量同样,都是一个命名空间,只不过变量是一段连续的内存空间别名,而域名则是IP地址的别名。

   那么到底域名具备什么样的表现形式呢?咱们以www.csdn.net为例,咱们能够看到它是一段字符串,而且在字符串中还带有“.”用于分割,每一个“.”分割的部分都表明了不一样层级的域名。

   咱们把最右边的部分,也就是net部分,称为顶级域名,而且层级向左依次下降。对于顶级域名下一层的二级域名,则是用于区分整个域名所属的单位,好比说属于csdn的bbs,属于163的bbs。而最左边的部分,称他为主机名,则是用于表示该主机的用途,也就是提供什么样的服务,好比说“www”表示该主机提供万维网服务。

   而域名系统它的内部,也是这样的一个构造,如图所示:

   最顶层的就是根域名服务器,它的做用是管理如com、net等这样的顶级域名服务器和返回相应的顶级域名服务器所表明的IP地址。

   而在根域名服务器下一个就是顶级域名服务器,它的做用就是管理如csdn、tencent等这样的权威域名服务器,并返回这些权威服务器所对应的ip地址。

   而第三层则是权威域名服务器,它的做用就是管理本身域名下的主机的ip地址。

   经过这样的构造,域名系统向外提供了一个域名解析服务。由于在上面的时候说过,域名只是IP地址的别名,实际上仍是须要经过MAC来访问主机。所以,咱们须要解析域名来得到相应的IP地址,再进一步解析IP地址为MAC地址来达到访问主机的目的。

   当咱们在浏览器输入一个域名按下回车访问时,这个域名就会在这个分层结构中从上到下查询,直到获取了域名相对应的IP地址。好比说,咱们访问“www.csdn.net”就会进行如下三次查询:

1.先访问根域名服务器,获得“net”顶级域名服务器的IP地址。
2.再访问顶级域名服务器,获得“csdn.net”权威服务器的IP地址。
3.最后访问权威服务器,获得“www.csdn.net”的地址。

   域名解析系统出现了之后,这样就足够了吗?实际上,随着在互联网上冲浪的人数愈来愈多,只有这样一个核心系统并不能知足需求,所以,“域名缓存”应时而出。

   所谓的域名缓存就是,像谷歌之类的大头公司或者网络运营商,创建本身的DNS服务器。当用户访问这个DNS服务器时,若是在这以前已经查询过这个域名的ip地址,就会直接返回该域名对应的IP地址,反之则会代替用户去访问根域名服务器,查询到相应的ip之后,会将这个ip地址缓存下来而后返回给用户。

   而在操做系统中,它会缓存对DNS解析后的结果,也就是对域名相应的IP地址进行缓存。在操做系统中有一个特殊的文件hosts,它就是用于保存主机映射的相关内容。也就是说,当咱们第二次访问“www.csdn.net”,它就不会再去DNS找相应的IP地址,而是直接经过操做系统中这个hosts文件拿到相应的IP地址。

   实际上,除了上述所提到的DNS服务器和操做系统之外,咱们所用的浏览器内部也会缓存DNS。

   经过这样的缓存思想,咱们就能够减轻域名解析的压力,提高用户的体验。

   最后,咱们来总结一下浏览器域名解析的一个过程,以下所示:

    1.浏览器发现地址栏中是域名(非数字)地址,检查浏览器缓存中是否有该域名对应的解析过的IP地址,若是有,结束域名解析。若是没有,则进行下一步。
    2.经过访问hosts文件查找操做系统中是否有缓存该域名对应的IP地址,若是有,结束域名解析。若是没有,则进行下一步。
    3.当hosts文件中没有缓存,那么就去找本地域名服务器(网络配置中的DNS服务器配置),也就是提到的大公司或者运营商提供的服务器,找相应的域名解析结果。若是有,结束域名解析。若是没有,则进行下一步。
    4.当浏览器、操做系统以及本地域名服务器都没有拿到相应的域名解析结果,就会向根目录域名服务器获取域名解析结果。而且缓存到本地

   经过上面的阐述,咱们就知道DNS的做用以及浏览器是如何从地址栏中获得输入的域名地址相对应的IP地,而后再进行相应的请求-应答过程。

  URI

   URI(Uniform Resource Identifier),中文名称是统一资源标识符。须要注意的是,它和URL(Uniform Resource Locator,统一资源定位符)特别类似,通常不会作严格区分,二者在样式是一致的,但其实在乎义上并非等同。

   实际上,URI是URN(统一资源名)和URL的合集,URI更准确来讲,是一个用来标识抽象和物理资源,而URL则是除了肯定资源之外,还须要提供定位该资源的访问机制。

   这里贴上维基百科中的一段解释:

统一资源名(URN)如同一我的的名称,而统一资源定位符(URL)表明一我的的住址。换言之,URN定义某事物的身份,而URL提供查找该事物的方法。

   咱们看一下URI最经常使用的一个形式,以下图所示:

   URI第一个组成部分是协议名,表示待访问资源应使用哪一种协议访问,好比说http、https以及ftp等等,浏览器辨识到相关协议时,就会调用相应的协议的API去作进一步的处理。而对于://这一段特定的字符串,则是用于区分协议名和后面的字符串部分。

   第二个组成部分就是表示访问的资源,里面包含了资源所在的主机以及在主机上的位置。对于主机名,在网络通讯协议中,它是必须存在的,而端口若是没有代表,就会根据协议名来使用默认的端口号。在这里须要注意的是:URI中的path部分必须以斜杆开头,也就是图中的红色加粗斜杠

   第三个组成部分则是查询参数,表示对资源定位的附加要求。好比说,咱们在使用搜索引擎的时候,会在地址栏看到path后面跟了多个参数,好比说百度的wd亦或者csdn中的p。

   因此有时咱们会看到地址栏会有特别长的字符串,都是由这三部分拼接而成的URI,它的做用就用于定位资源。

 HTTP剖析

   在了解完相关的概念之后,接下来咱们对HTTP进行剖析。

  环境搭建

   为了更好研究HTTP,接下来,咱们经过几个软件来搭建一个演示环境,以下所示:

一个请求方——浏览器,Chrome或者Firefox。
一个应答方——服务器,这里用Linux中的Nginx代替。
一个抓包工具——Wireshark。它用于截取TCP/IP协议栈中传输的流量

   对于软件的下载安装在这里不予以讲述,自行查询。在安装好相应的软件之后,为了可以经过域名访问到这个主机,咱们还须要在客户端中的hosts文件中添加相关的信息,以下所示:

192.168.0.211 www.cexample.com

   那么接下来咱们启动Nginx,访问该网页,结果如图所示:

   能够看到咱们能够访问到该页面,那么接下来咱们使用WireShark开始进行抓包处理。

  HTTP初剖析

   须要注意的是,这里咱们过滤器须要设置为HTTP TCP PORT(80)用于只抓取和HTTP相关的包,如图所示:

   接下来咱们进行抓包,打开浏览器访问192.168.0.211,当响应结束之后,咱们将抓包中止,结果以下所示:

   须要注意的是:有多个TCP流时,能够在上方的过滤器中填入表达式:tcp.stream eq 0 筛选出第一个完整的TCP流。

   首先咱们能够从图中看到,当咱们在浏览器的地址栏中使用了HTTP访问192.168.0.211时,它会先创建TCP链接,这是由于HTTP协议就是运行在TCP/IP协议之上的。那么,根据TCP协议,浏览器须要通过“三次握手”和服务器创建可靠的链接。也就是抓取的数据包中的前三个,如图所示:

   能够看到,经过SYN,SYN/ACK,ACK三个包之后,浏览器和服务器的TCP链接就创建起来了。在创建好TCP链接之后,浏览器就向服务器发送了一个格式化的报文,也就是数据包中的第四个包,以下所示:

   当web服务器接收到报文后,就会解析报文而且进行相应的请求处理行为。那么这里咱们是访问根路径下的默认文件index.html,那么web服务器就会将这个文件的内容再根据HTTP规定的格式发送给客户端,也就是如下这个包:

   当浏览器收到这个包的时候,会向服务器发送一个ACK,告诉服务器已经接收到了发送的响应。那么当接收到这个响应报文后,浏览器就会去解析这个报文。

   当解析到是一个HTML文件的时候,浏览器就会调用内置引擎去处理这个文件,而且将内容渲染给用户。

   而最后四个包则是“四次挥手”,不是本文的重点,在此略过。

   那么这上面的整一个过程,就是浏览器接收到用户的请求后,向服务器发起HTTP请求后的一个简单过程。咱们经过域名访问也是一样的结果。

   在前面的时候也说过,在传输当中能够有中介,好比说CDN亦或者负载均衡服务器。那么,在现实环境中,并非上面这么纯粹简单的传输过程,这里只是演示最简单的过程,只须要知道HTTP传输,客户端和服务端大体都作了什么便可。

   在了解完HTTP的请求-应答之后,咱们再来了解在上面提到过HTTP的传输的核心:传输的报文内容。接下来咱们就来了解一下这个请求报文中的具体结构。

  HTTP再剖析

   HTTP传输的报文分为两种:请求报文响应报文,而一个完整的HTTP报文以下所示:

   对于起始行和头部,咱们根据两类报文又分别合称为“请求头”和“响应头”,而消息正文又称为“实体”(body)。HTTP协议规定,报文中能够没有实体内容,但必须有header,好比get请求获取资源。而且,在header的下一行必须为空行(CRLF)。

 请求报文

   接下来,咱们来看一下刚刚包中的GET / HTTP/1.1,以下所示:

   如图上所示,第一个橙色框中的GET / HTTP/1.1就是请求行,在第一行下面的黄色框内的就是header,而最后红色框的是一个\r\n,也就是一个CRLF。

   接下来咱们分别对这三个部分进行讲解,首先是请求行,咱们点开该列表项,显示以下:

   请求行由三部分组成,从左到右分别是请求方法、请求URI以及HTTP协议版本号,以下所示:

   请求URI用于定位资源,请求方法表示服务端对资源的操做方式。HTTP/1,1中定义了八种方法,以下所示:

请求方法 含义
GET 获取资源
HEAD 获取资源的元信息
POST 向资源提交数据(非幂等)
PUT 向资源提交数据(幂等)
DELETE 删除资源
CONNECT 创建特殊的链接隧道
OPTIONS 列出可对资源实行的方式
TRACE 追踪请求-应答的传输路径

   须要知道的是:请求方法是客户端向服务器发送操做资源的请求,并非客户端就可以决定服务器执行该操做,服务器是有权力拒绝客户端的请求

  GET/HEAD

   那么接下来咱们来稍微了解一下前面四个请求方法,首先是GET方法,它表示请求从服务器获取资源。通常来讲,获取的资源大多数是一个页面,页面能够是静态的也能够是动态的。而资源还能够是其余格式的,好比说JSON字符串。

   那么实际上,GET方法只是客户端告诉服务器:我要申请URI表示的这个资源,可是返回给客户端的数据是由服务器的实现来决定的。

   而HEAD方法和GET方法近乎一致,不管是本质上仍是服务器的相应处理上,它们的差异在于返回体。当服务器解析到请求方法为HEAD并作了必定的处理后,它会返回给客户端响应,可是这个响应里面只有响应头,没有响应体,这在必定程度上避免了传输实体数据的浪费。

   那么讲完了GET/HEAD两兄弟之后,咱们就要来说POST/PUT两兄弟了。

  POST/PUT

   POST方法和GET方法相反,它是向服务器发送数据,也就是说,它是告诉服务器一些信息,这些信息保存在报文的请求体中。

   这就比如咱们使用聊天软件,按下“发送”按钮时,会将输入框中的文字放进报文的请求体里,而后拼接上相应的请求头,发送给服务器。

   而PUT方法和POST方法有些许相似,也是向服务器发送数据,可是一般咱们将POST表示建立一个资源,而PUT表示修改一个资源。实际应用大多数以POST为主。

   在上面的表格中还附加了幂等和非幂等。所谓的幂等就是无论进行多少次重复的行为,都会实现相同的结果。实际上除了POST不是幂等方法之外,其余方法都是幂等方法。

   在请求行的下面就是首部字段,这些字段和请求行一块儿构成了HTTP报文中的请求头。

   首先咱们来看它的组成,首部字段由多个键值字符串组成,键和值之间用冒号分割。特别须要知道的是:首部字段除了用HTTP规范的已有字段,还能够任意地添加自定义的字段。

   HTTP协议规定了特别多的首部字段,这些字段都有各自的用处而且大多数的字段都有重要的做用。好比说,Accept-Charset是告知服务器客户端能接受的字符集。再好比Cache-control字段,它是用于控制缓存的,和max-age一块儿发挥做用。

   咱们来看一下刚刚那幅图上的首部字段,以下所示:

   这里挑几个首部字段来说,首先是最重要的Host字段。为何说它最重要呢?由于若是报文中没有Host字段,就不是一个正确的报文。这是由于HTTP规范中规定Host字段有且仅能出如今请求头里。

   Host字段是用于告诉服务器应该是哪台主机去处理当前请求,好比在192.168.0.211上有多个虚拟主机:www.cexample.com、www.scorpion.com等等。当咱们经过域名访问时,就得告知服务器咱们访问的是哪个域名,也就是指明Host字段。若是不指明Host字段,服务器就不能让域名对应的主机去处理请求。

   下面的Connection字段它的用处有两个:能够用于控制再也不转发给代理服务器的首部字段、能够用于管理长链接。在HTTP/1.1开始这个字段的值默认就是keep-live,也就是长链接。

   咱们再来看User-Agent,它的做用就是告诉服务器,发起HTTP请求的客户端哪个浏览器,而后服务器根据这个字段的值来返回该浏览器能显示的页面。

   最后咱们再来看一个在图中并无出现的一个字段Content-Length。实际上它属于和实体有关的字段,它表示报文中实体的长度,也就是请求头或响应头空行后面数据的长度。若是没有指定该字段,服务器就会用chunked编码的方式来分段传输数据。

 响应报文

   其实响应报文和请求报文没有多大的区别,他们可见的区别就在于第一行。请求报文中将第一行称为请求行,而响应报文将第一行称为状态行。

   状态行表示的是服务器接收到请求后响应的状态,它的结构以下所示:

   咱们对照着抓包中的响应报文中的状态行来看,以下所示:

   其中,HTTP/1.1就是报文使用的HTTP协议的版本,200就是状态码的一种,表示请求已经收到而且会返回请求须要的资源。然后面的OK,则是表示对状态码的解释说明。

   接下来咱们来看一下在状态行中最有用的状态码,它表示服务器对请求的一个处理结果,能够是“正确”的结果,也能够是“错误”的结果。也就是说,不管返回的状态码是什么样的,客户端均可以根据状态码来作相应的调整处理

   状态码由三位数字组成,其中,第一位表示状态码的类别,剩下两位用于区分同类不一样种状态的描述。在RFC标准中规定了状态码有五类,以下所示:

状态码类别 具体含义
1xx系列 临时响应状态码,表示当下时刻是协议处理的中间状态,须要进一步的操做
2xx系列 成功状态码,表示请求报文已经收到而且正常处理完毕
3xx系列 重定向状态码,表示客户端请求的资源发生了变更,须要进行更多操做来实现请求
4xx系列 错误状态码,表示客户端发送的请求报文有误
5xx系列 错误状态码,表示服务器内部错误

   RFC规范中有50多个状态码,但实际上咱们在使用一些web服务器的时候,咱们会发现除了RFC规范里的,还有不在规范中的状态码。好比说Nginx中的499,它表示服务器请求过多,客户端在有效时间内没有获得响应,就自行关闭链接。

   那么,接下来详细介绍一部分状态码。

  1xx系列

   对于1xx类的状态码,咱们只了解一个101,它是指根据首部字段Upgrade来提高协议。意思就是,客户端在请求报文中附加Upgrade首部字段告知服务器须要升级协议,而服务器也会相应的返回101状态码告知客户端也要升级协议。好比说从HTTP/1.1到HTTP/2或者从HTTP协议到WebSocket协议的变化。

  2xx系列

   对于2xx类的状态码,咱们在学习中最多见的就是200,它表示服务器返回了客户端想要的响应结果。和200有相近含义的就是204,它一样也是表示返回了想要的响应结果,可是响应报文内没有实体数据,也就是说,响应头后面只有空行没有body。

   还有一个比较常见的状态码206,它和下载有关系,也一样是表示成功的含义,可是它更多表示的是服务器已经处理了部分GET请求。这个状态码是HTTP分块下载或断点传输的基础,好比说迅雷这类HTTP下载工具,都是使用这个来实现分块下载和断点续传的功能。

   这个状态码206,每每会须要请求报文中包含Content-Range首部字段来告诉服务器,客户端但愿获得的内容范围,也就是服务器返回的响应报文中实体数据的具体范围。除此以外,请求报文中还能够附带If-Range首部字段来限制范围请求。

   那么从上面的描述中,能够知道206是范围请求的成功标识。若是请求的范围超过了资源总大小,也就是越界状况产生的时候,服务器会返回一个416状态码。这里须要注意的是,若是服务器不支持范围请求这样的响应机制,就会直接返回一个200状态码而且附带整个实体数据给客户端。

  3xx系列

   说到3xx类状态码,咱们最熟悉的就是30一、302,301状态码表示永久重定向,而302则是临时重定向。

   对于301和302,服务器都要在响应头中使用Location首部字段来指明要重定向的URI,它们的表现形式都是跳转到另外一个URI上。

   那么到底什么是永久重定向和临时重定向呢?永久重定向就是指这次请求的资源不存在,须要改用另外一个URI再次访问。而临时重定向则是这次请求的资源仍然存在,可是须要暂时用另外一个URI来访问。

   描述看起来很类似,其实实际上在表现上就很是明显。好比说,咱们访问a.html的时候,服务器返回了一个301状态码给客户端,而且附带一个Location:b.html,那么咱们就会在地址栏上明显地看到地址栏发生了变化:从a.html变为b.html。而若是返回302状态码给客户端,咱们会发现地址栏依旧没有变化,仍然是a.html。

   进一步地说,其实301重定向可以告诉用户网站域名的变更,而302重定向没法告知用户网站域名已经变更了。

   特别补充一点:当浏览器收到302状态码的时候,它就不会作缓存优化这个操做,也就是说,下一次请求这个资源的时候,仍然用原来的地址访问。

   在3xx系列中还有一个不太名副其实的304状态码,由于它并无具有上述30一、302的那种跳转含义,可是又称它为缓存重定向,也就是重定向到已缓存额文件。

   这里再次抓包,结果以下所示:

   能够看到,咱们访问默认根路径下的index.html在上一次访问已经缓存了,再次请求这个资源的时候,服务器给咱们返回了一个304状态码。

  4xx系列

   谈到4xx系列的状态码,或许咱们就会直接想到404状态码,毕竟这是咱们最常看见的一个状态码了,也是咱们最不想看到的状态码。

   在讲404以前,咱们先来说一下403。4xx系列默认都是客户端的请求发生了错误,而403实际意义倒是服务器禁止该请求,通常相应的会返回一个拒绝请求的页面,上面会说明拒绝的理由。

   那么404呢,本来的使用状况是当请求所但愿获得的资源在服务器上没找到的时候,服务器就会返回这样一个状态码,可是现阶段被模糊化了。这是由于可能请求的资源没找到,也有多是拒绝访问该资源,缘由无从而知,因此其实这个状态码已经被模糊化了。

   其实除去上述这两个已经被模糊化的状态码之后,剩下的4xx系列状态码是很是好理解的,好比说405(Method Not Allow)、408(Request Timeout)或者429(Too Many Requests)以及401(Unauthorized)。

  5xx系列

   若是客户端请求报文正确的状况下,服务器处理时内部出了问题,就会返回5xx系列的状态码。

   咱们须要知道的是,服务器返回出错的状态码,不该该过于明文告知客户端,这是基于安全性的考虑。因此相比于4xx系列中的400来讲,5xx系列的500就是很是有必要的。

   500状态码(Internal Server Error)它不会告诉客户端服务器究竟发生了什么样的错误。

   而其余的5xx系列状态码就很是浅显易懂了,好比说501(Not Implemented)能够表示该功能未实现。再好比说502(BadGateWay),它表示做用为网关或代理的服务器访问后一个服务器时发送了错误。还有一个最多见的状态码503(Service Unavailable),在高并发场景下一般会看到,表示当前服务器繁忙,没法响应请求。

   最后,咱们来总结一下状态码:咱们能够将状态码理解为客户端和服务端沟通的语言。状态码不是只须要对其中一个负责,而是须要对客户端和服务端二者共同负责。

 报文实体

   在上面了解了两类报文的头部,而它们的实体数据尚未述说,那么接下来咱们开始了解HTTP中报文的实体部分。

   对于实体部分,它能够包含多种不一样的内容,好比说文本、图像以及音频等等。那么在这么多种内容的状况下,做为客户端或者做为服务器,也就是上层应用,获取到了实体之后,如何才能知道实体部分到底属于哪一种类型的数据呢?

   那就是经过MIME(Multipurpose Internet Mail Extensions)规范,也就是所谓的多用途互联网邮件扩展,来告知上层应用HTTP报文中实体内容的数据类型,而在报文中就经过首部字段Content-Type来代表。

   Content-Type的值以斜杠划分,斜杆前表示数据类型,斜杠后表示数内容的格式。好比说最多见的text/html,前面是文本的数据类型,后面是实体内容是html。

   有了Content-Type就能让上层应用知道实体数据中究竟是什么,可是每每咱们传输的数据可能很是的大,为了传输效率,就会将内容压缩。而若是咱们将内容压缩了,上层应用就不知道这个数据本来的样子是什么。所以,HTTP中还提供了一个Content-Encoding。

   Content-Encoding的值咱们最多见的就是gzip亦或者deflate,对于它们的区别在这里不讲述。

   这上面所讲的Content首部字段都是HTTP协议中服务器用来告诉客户端发送了什么类型的数据,而咱们说过协议是对二者之间的规范和协商,那么一样的,客户端也理应告诉服务端本身能接收什么类型的数据。

   所以,HTTP协议还提供了和Content-Type相对的首部字段Accept以及和Content-Encoding相对的首部字段Accept-Encoding。

   接下来,咱们来看一下上面抓的请求包和向响应包中的首部字段,以下所示:

   这里须要注意的是,虽然图中Content-Type只有text/html,实际上它后面还能跟一个charset,以下所示:

Content-Type: text/html; charset=utf-8

   看到charset和utf-8就应该明白这是在指定字符集,可是实际上如今这个值已经不太常用了,只须要知道有这一个东西就好。

   这里比较值得说的是,在图中咱们能够看到一个很奇怪的字符q,这是表明了权重的意思,也就是quality factor,它是用于表示优先级,最大值为1,最小值为0.01。它的值还能够为0,指的是拒绝这类文件。

   好比说,图中的这一段:

Accept: text/html,[中间省略]application.xml;q=0.9

   若是q没有指定的时候,就默认为1,也就是最大优先级。这段就表示浏览器最但愿接收到的数据格式是HTML文件,其次是xml文件,依次顺序下去。服务器收到这样的请求头的时候,会进行权重的计算,而后输出相应的格式给客户端。

结束语

''' 在这一章只是初步的对HTTP作了一个稍微详细的介绍 实际上HTTP包含了很是多的东西,也牵扯很是多的知识 应用层的协议不止HTTP,还有FTP、SSH等等,可是可以独占鳌头的倒是HTTP 这是由于HTTP协议是一个很是开放的传输协议,好比说任意首部字段、状态码、实体数据等等 固然HTTP也有它很差的地方,好比“明文传输”,好比“完整性校验”,还有和它夕夕相伴的“无状态” 在接下来的一章将会讲述HTTP中几个内置机制:链接管理、缓存代理等等 '''