图解系列果然是通俗易懂的好书,在本书的第一章竟然不是直接介绍 HTTP
的概念(《HTTP权威指南》
上来就是给啃概念了),而是引入了这样的一个问题:
在网页浏览器的地址栏中输入URL按下回车时,Web页面是如何呈现的?
—— 然而书上也没有很官方的给出回答,只是说信息被发往某处,然后从某处返回一个页面就是咱们看到的页面。接着说到,像这种从服务器获取文件资源等信息的,都可以被称为客户端,返回结果(响应)的被称为服务器。也就是说,客户端跟服务器之间是存在通信的,那么它们之间到底是如何通信的呢,客户端又是怎么精确的找到服务器上的资源呢?这里面一切的一切都是 HTTP
规定的,对的,HTTP
就是一个协议,它规定着客户端与服务器通信的准则。
HTTP
协议,全称为 HyperText Transfer Protocol 意为超文本传输协议
。它诞生于90年代,起初的诞生的设想就是用于让远隔两地的研究者们共享知识。最初设想的基本理念:借助多文档之间相互关联形成的超文本,连成可相互参阅的 WWW(World Wide Web),万维网
。WWW
是浏览器当年用来浏览超文本的客户端应用程序时的名称。现在则用来表示这一系列的集合,也可以称为 Web
。
为理解 HTTP
,非常有必要先了解 TCP/IP
协议族。因为通常使用的网络(包括互联网)是在 TCP/IP
协议族的基础上运作的,而 HTTP
属于它内部的一个子集。**计算机与网络设备要相互通信,双方就必须基于相同的方法。**比如,如何探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎么结束通信等规则都需要事先确定。不同的硬件、操作系统之间的通信,所有的这一切都需要一种规则。而我们就把这种规则称为协议。
TCP/IP
协议族里重要的一点就是分层。TCP/IP
协议族按层次分别分为以下4层:**应用层、传输层、网络层和数据链路层。**分层是有好处的,比如,如果互联网只由一个协议统筹,某个地方需要改变设计时,就必须把所有部分整体替换掉。而分层之后只需把变动的层替换掉即可。把各层之间的接口部分规划好之后,每个层次内部的设计就能够自由改动了(感觉这跟分模块开发或者说跟微服务是同一个思想,分而治之)。
-
应用层
应用层决定了向用户提供应用服务时通信的活动,
HTTP
协议正是处于该层。 -
传输层
传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。
-
网络层
网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位(打游戏的都知道丢包率或者丢包的概念,这里所丢的包其实就是数据包)。该层规定了通过怎样的路径到达对方计算机,并把数据包传送给对方。
-
链路层(又称为数据链路层,网络接口层)
用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动等物理可见部分。硬件上的范畴均在链路层的作用范围。
利用 TCP/IP
协议族进行网络通信时,会通过分层顺序与对方进行通信,发送端从应用层往下走,接收端则从应用层往上走。
以 HTTP
来举例:发送端的客户端在应用层发出了一个 HTTP
请求,接着,为了传输方便,在传输层把应用层收到的数据(HTTP报文
)进行分割,并在各个报文上标记序号以及端口号转发给网络层。在网络层,增加作为通信目的地的 MAC
地址后转发给链路层。接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。
发送端在层与层之间传输数据时,每经过一层必定会被打上一个该层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。
按层次分,IP
协议位于网络层,作用是把数据包传送给对方。而要确保信息传送过去则需要满足各种各样的条件,比如说最重要的条件是 IP
地址和 MAC
地址。IP
地址指明了节点被分配到的地址,MAC
地址是指网卡所属的固定地址。IP
地址可以和 MAC
地址进行配对,IP
地址可变换,但 MAC
地址基本不会改变。
IP
间的通信依赖于 MAC
地址。在网络上,通信的双方在同一局域网内的情况是很少的,通常是经过多态计算机和网络设备中转才能连接到对方。而在进行中转时,会利用下一站中转设备的 MAC
地址来搜索下一个中转目标。这时,会采用 ARP
协议。ARP
协议是一种用以解析地址的协议,根据通信方的 IP
地址就可以反查出对应的 MAC
地址。
按层次分,TCP
位于传输层,提供可靠的字节流服务。所谓的字节流服务是指,为了方便传输,将大块数据分割成以报文段为单位的数据包进行管理。而可靠的传输服务是指,能够把数据准确可靠地传给对方。
为了准确无误将数据送达目标处,TCP
协议采用了三次握手策略。用 TCP
协议把数据包送出去后,TCP
不会对传送后的情况置之不理,它一定会向对方确认是否成功送达。
握手过程中使用了 TCP
的标志 —— SYN
和 ACK
。发送端首先发送一个带有 SYN
标志的数据包给对方。接收端收到后,回传一个带有 SYN/ACK
标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK
标志的数据,代表握手结束。若在握手过程中某个阶段中断,TCP
协议会再次以相同的顺序发送相同的数据包。
DNS
,全称为 Domain Name System
,意为:域名系统,是和 HTTP
协议一样位于应用层的协议。它提供域名到 IP
地址之间的解析服务。
请求资源的一端称为客户端,提供资源响应的一端称为服务器端。在应用 HTTP
协议时,必定是一端担任客户端角色,另一端担任服务器角色。
HTTP
协议规定,请求从客户端发出,最后服务器端响应请求并返回。换句话说,肯定是先从客户端开始建立通信的,服务器端再没有接收到请求之前不会发送响应。示例:
下面则是从客户端发送个服务器端的请求报文中的内容:
GET /index.htm HTTP/1.1
Host:hackr.jp
起始行开头的 GET
表示请求访问服务器的类型,称为方法。随后的字符串 /index.htm
指明了请求访问的资源对象,也叫做请求 URI
。最后的 HTTP/1.1
是指使用的是 HTTP
协议的 1.1 版本。
HTTP
是一种不保存状态,即无状态的协议。HTTP
协议自身不对请求和响应之间的通信状态进行保存。也就是说,在 HTTP
这个级别,协议对于发送过的请求或响应都不做持久化处理。(附上有趣的图)
虽然 HTTP
是无状态协议,但是为了实现保持状态的功能,如今也有很多技术可以解决了,比如说 Cookie
或 Session
等等。详细内容后面讲解。
GET
方法用来请求访问已被 URI
识别的资源。指定的资源经过服务端解析后返回响应内容。
POST
方法用来传输实体,表示增加某个内容
通过 PUT
方法请求服务器修改某个内容
通过 DELETE
方法请求服务器删除某个内容
以上四个方法都是常用的,而且都符合 RESTful
风格的,四个方法分别对应着增删改查。
在 HTTP
协议的初始版本中,每进行一次 HTTP
通信就要断开一次 TCP
连接,以当年的通信情况来说,因为都是些容量很小的文本传输,所以即使这样也没有多大问题。可随着 HTTP
的普及,文档中包含大量图片的情况多了起来。比如,使用浏览器浏览一个包含多张图片的页面时,在发送请求访问 HTML
页面资源的同时,也会请求该 HTML
页面里面包含的其他资源。因此,每次的请求都会造成无谓的 TCP
连接建立和断开,增加通信量的开销。
为了解决上面 TCP
连接的问题,HTTP/1.1
想出了持久连接,也称为 HTTP keep-alive
。持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP
连接状态。持久连接的好处在于减少了 TCP
连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。在 HTTP/1.1
中,所有链接默认都是持久连接。
持久连接使得多数请求以管线化方式发送成为可能。从前发送请求后需要等待并收到响应,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求。所以,管线化技术比持久连接还要快。请求数越多,时间差就越明显。
HTTP
是无状态协议,它不对之前发生过的请求和响应的状态进行管理。但是在很多场景下更需要的是保存一个状态,比如要求登录验证的页面本身无法进行状态管理(不记录已登录的状态),那么每次跳转新页面不是要再次登录,就是要在每次请求报文中附加参数来管理登录状态。
不可否认,无状态协议当然有它的优点,由于不必保存状态,自然可减少服务器的 CPU
以及内存资源的消耗。从另一侧面说,也正是因为 HTTP
协议本身是非常简单的,所以才会被应用在各种场景里。保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了 Cookie
技术。Cookie
技术通过在请求和响应报文中写入 Cookie
信息来控制客户端的状态。
Cookie
会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie
的首部字段信息,通知客户端保存 Cookie
。当下次客户端再往该服务器发送请求时,客户端会自动再请求报文中加入 Cookie
值后发送出去。服务器发现客户端发送过来的 Cookie
后,会去检查究竟是从哪一个客户端发送的链接请求,然后对比服务器上的记录,最后得到之前的状态信息。
简单总结:Cookie
是由服务器端生成的,在浏览器端保存。
用于 HTTP
协议交互的信息被称为 HTTP
报文。请求端(客户端)的 HTTP
报文叫做请求报文,响应端(服务器端)的叫做 HTTP
响应报文。HTTP
报文本身是又多行数据构成的字符串文本。
HTTP
报文大致可分为报文首部和报文主体两块。两者之间通过一个空行来划分。
-
请求行:包含用于请求的方法,请求
URI
和HTTP
版本。示例:GET www.baidu.com HTTP/1.1
-
状态行:包含表示响应结果的状态码,原因短语和
HTTP
版本 -
首部字段:包含表示请求和响应的各种条件和属性的各类首部
HTTP
在传输数据时可以按照数据原貌直接传输,但也可以在传输过程中通过编码提升传输速率。通过在传输时编码,能有效的处理大量的访问请求。但是,编码的操作需要计算来完成,因此会消耗 CPU
资源。
- 报文,是
HTTP
通信中的基本单位,由 8 位组字节流组成,通过HTTP
通信传输。 - 实体,作为请求或响应的有效载荷数据被传输,其内容由实体首部和实体主体组成。
通常,报文主体等于实体主体。只有当传输中进行编码操作时,实体主体的内容发生变化,才导致他们产生差异。
向待发送邮件内增加附件时,为了使邮件容量变小,我们会先用 ZIP
压缩文件之后再添加附件发送。 HTTP
协议中有一种被称为内容编码的功能也能进行类似的操作。
内容编码指明应用在实体内容上的编码格式,并保持实体信息原样压缩。内容编码后的实体由客户端接收并负责解码。
以前,用户不能使用现在这种高速的带宽访问互联网,一旦下载比较大的资源时就很费力了。如果下载过程中遇到了网络中断的情况,更是崩溃了。为了解决上述问题,需要一种可恢复的机制。所谓恢复就是指能从之前下载中断处恢复下载。要实现该功能需要指定下载的实体范围 Range Request
。
执行范围请求时,会用到首部字段 Range
来指定资源的 byte
范围。形式如下:
-
m ~ n
字节Range:bytes=m-n
-
m
字节之后全部
Range:bytes=m-
-
一开始到
m
和n ~ p
字节的多重范围Range:bytes=-m,n-p
针对范围请求,响应会返回状态码为 206 。另外,对于多重范围请求,响应会在首部字段 Content-Type
标明 multipart/byteranges
后返回响应报文。
状态码的作用是当客户端向服务器发送请求时,描述返回的请求结果。也就是说,通过状态码就能简单的判断服务器处理的结果是什么了。响应状态码都是由三位数字组成的,其中第一位数字表示响应的类别,后两位无分类。响应类别有以下5种:
200
—— 表示请求处理成功204
—— 表示处理成功,但是没有内容返回206
—— 处理成功,这是一个带有请求范围的请求403
—— 服务器端拒绝访问,爬虫常见404
—— 找不到资源500
—— 服务器内部错误
代理,是一种有转发功能的应用程序,它扮演了位于服务器和客户端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。
代理服务器的基本行为就是接收客户端发送的请求后转发给其他服务器。代理不改变请求 URI
,会直接发送给前方持有资源的目标服务器。持有资源实体的服务器称为源服务器。从源服务器返回的响应经过代理服务器后再传给客户端。在 HTTP
通信过程中,可级联多台代理服务器。请求和响应的转发会经过数台类似锁链一样连接起来的代理服务器。转发时,需要附加 Via
首部字段以标记出经过的主机信息。
每次经过代理服务器时都会追加首部 Via
。
使用代理服务器的理由有:利用缓存技术减少网络带宽的流量,组织内部针对特定网站的访问控制等等。代理有多种使用方法,按两种基准分类,一种是是否使用缓存,另一种是是否会修改报文。
- 缓存代理:代理转发响应时,缓存代理会预先将资源的副本(缓存)保存在代理服务器上,当代理服务器再次接收到相同资源的请求时,就可以不去源服务器获取资源,而是将之前缓存的资源作为响应返回。
- 透明代理:转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理。反之称为非透明代理。
网关,是转发其他服务器同喜数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。网关的工作机制跟代理十分相似,而网关能使通信路线上的服务器提供非 HTTP
协议服务。利用网关能提高通信的安全性,因为可在客户端与网关之间的通信线路上加密以确保连接的安全。
隧道,是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方通信连接的应用程序。隧道可按要求建立起一条与其他服务器的通信线路,届时使用 SSL
等加密手段进行通信。隧道的目的是确保客户端与服务器进行安全的通信。隧道本身不会去解析 HTTP
请求。也就是说,请求保持原样中转给之后的服务器。隧道会在通信双方断开连接时结束。
缓存是指代理服务器或客户端本地磁盘内保存的资源副本。利用缓存可减少对源服务器的访问,因此也就节省了通信流量和通信时间。缓存服务器时代理服务器的一种,当代理转发从服务器返回的响应时,代理服务器将会保存一份资源的副本。
先回顾 HTTP
报文的结构:报文首部 + 空行 + 报文主体。HTTP
协议的请求和响应报文中必定包含 HTTP
首部。首部内容为客户端和服务器分别处理请求和响应提供的信息。
在请求中,HTTP
报文由方法、URI
、HTTP
版本、HTTP
首部字段等部分构成;在响应中,HTTP
报文由 HTTP
版本、状态码、首部字段构成。
HTTP
首部字段是构成 HTTP
报文的要素之一。在客户端与服务器之间以 HTTP
协议进行通信的过程中,无论是请求还是响应都会使用首部字段,它能起到传递信息的作用。
使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等。