阅读 434

HTTP协议 | 七日打卡

楔子

身为一名前端程序员,每天必不可少的就是和 HTTP 打交道,然而实际上很多的前端程序员甚至是工作多年老手都对 HTTP 只是 知其然不知其所以然
当被人问到 HTTP工作方式、HTTP协议结构、HTTP通讯原理、HTTP协议特性、HTTP0.9、HTTP1.1、HTTP2、HTTP3、HTTPS等等可能大部分人就傻眼了。
想在网上进行学习又会发现资料过于繁杂不成体系,甚至可能还有错误的内容。而且一般的内容都太过于表面,最重要的是像这种偏于底层原理的东西学习过程非常枯燥,很难坚持下去。
所以我就来看看我能坚持下去不,滑稽脸。

学习资料和参考资料:

  1. 大话HTTP协议
  2. 百度百科
  3. 等等(别问我等等是谁!)

HTTP 初相识

我们先来认识一下 HTTP协议,来对它有一个初步的认识。

什么是 HTTP 协议

HTTP 是 HyperText Transfer Protocol 的缩写,翻译过来就是 超文本传输协议
HTTP 是因特网上应用最为广泛的一种网络传输协议,所有的 WWW 文件都必须遵守这个标准。
HTTP 是一种 通信协议, 它允许在计算机世界里专门的两点之间传输文字、图片、音频、视频等超文本数据。
HTTP 是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于 1990 年提出,经过几年的使用与发展,得到了不断的完善和扩展。

WEB 与 HTTP

WEB 是一种基于超文本和 HTTP 的、全球性的、动态交互的、跨平台的分布式 图形信息系统
建立在 Internet 上的一种 网络服务,为浏览者在 Internet 上查找和浏览信息提供了图形化的、易于访问的直观界面,其中的文档及超级链接将 Internet 上的信息节点组织成了一个互为关联的网状结构。

HTTP协议的前世今生

  1. 1990年10月 万维网之父 TimBeners-Lee 最早提出了 HTTP协议
  2. 1991年 HTTP0.9诞生(规定了 HTTP 使用 TCP/IP链接,只有 get 一个请求方法,加上请求的 URI,响应则直接返回 HTML文本也无法区分错误消息和正确消息,都是短链接)
  3. 1996年5月 HTTP1.0发布(在 HTTP0.9 的基础上进行了大量了的扩充和改进,比如请求头和响应头,状态码,重定向,增加了 head 和 post 方法,响应对象也不再局限于必须的是 HTML文本,也支持一些长连接,增加了缓存机制等等)
  4. 1997年1月 HTTP1.1发布(1999年6月一个新的规范取代了它,HTTP1.1是目前用的最多的协议,增加了 options、put、delete、patch、connect、持久连接、管道机制、分块传输等等)
  5. 2015年5月 HTTP2.0提出(提高传输性能,实现低延迟和高吞吐量,其他的和 HTTP1.1 的基本一样)
  6. HTTP3.0 基于 QUIC协议( QUIC协议 是基于 UDP 的,无需连接,但是 UDP 不是很可靠。QUIC协议 是谷歌在2013年提出的,主要目标就是减少基于 TCP/IP 带来的通讯延迟和其他的开销,谷歌再 UDP 这个基础之上做了很多的改进,试图以 UDP 的效率提供 TCP 的可靠性,把二者合二为一,然后反正是没被采纳,RETF 2016年成立了一个专项组,自己又重新做了一套(和谷歌的没有什么本质上的区别吧!))

透过 TCP/IP 看 HTTP

HTTP协议是构建在TCP/IP协议之上的,是TCP/IP协议的一个子集

TCP/IP协议族

TCP/IP协议其实是一系列与互联网相关联的协议集合起来的总称。
分层管理是TCP/IP协议的重要特征。
TCP/IP协议族是由一个四层协议组成的系统,这四层分别为:

  1. 应用层
  2. 传输层
  3. 网络层
  4. 数据链路层

应用层

应用层一般是我们编写的应用程序,决定了向用户提供的应用服务。
应用层可以通过系统调用与传输层进行通信。
例如:FTP、DNS、HTTP

传输层

传输层通过系统调用向应用层提供处于网络连接中的两台计算机之间的数据传输功能。
传输层中有两个性质不同的协议:TCP、UDP
TCP 是面向连接的,所以 TCP 比较可靠,但是因为要建立连接所以效率就比较低一点。
UDP 是无连接的,因为 UDP 是没有连接的,所以它的效率很高,但是因为没有建立连接所以无法进行一些校验机制,因此可靠性就比较低一点。
在实际的使用中,具体使用哪种协议,需要根据场景进行决定的。

网络层

网络层用来处理再网络上流动的数据包,数据包是网络传输的最小数据单位。
该层规定了通过怎样的传输路线到达对方计算,并把数据包传递给对方。

链路层

链路层用来处理连接网络的硬件部分,包括控制操作系统、硬件设备驱动、NIC(Network Interface Card, 网络适配器)以及光纤等物理可见部分。
硬件上的范畴都在链路层的作用范围之内。

数据包的封装过程

应用程序在发布数据到我们的数据网络之前,会沿着这个协议栈,从上往下去进行传递。
每层协议都会在上一层的基础之上,加上自己的头部信息,链路层还会加上尾部信息。

HTTP数据传输过程

发送端发送数据的时候,数据会从上层传输到下层,且每经过一层都会被打上该层的数据头部信息。
而接收端接收数据的时候,数据会从下层传输到上层,传输前会把下层的头部信息删除。

TCP 三次握手(传输层)

使用TCP协议进行通信的双方必须先建立连接,然后才能开始传输数据。
为了确保连接双方的可靠性,双方建立连接的时候,TCP协议采用了三次握手的策略。

第一次握手

客户端发送带有 SYN 标志的连接请求报文段,然后进入 SYN_SEND 状态,等待服务端的确认。

第二次握手

服务端接收到客户端的 SYN 报文段后,需要发送 ACK 信息对这个 SYN 报文段进行确认, 同时还要发送自己的 SYN 请求信息。
服务端会将上述的信息放到一个报文段( SYN + ACK 报文段 )中,一并发送给客户端,此时服务端将会进入 SYN_RECV 状态。

第三次握手

客户端接收到服务端的 SYN + ACK 报文段后,会向服务端发送 ACK 确认报文段,这个报文段发送完毕后,客户端和服务端都进入 ESTABLISHED 状态,完成 TCP 三次握手。

DNS 域名解析

通常我们访问一个网站,使用的是主机名或者域名来进行访问的。
因为相对于 IP 地址,域名更容易让人记住。
但是 TCP/IP 协议使用的是 IP 地址进行访问的,所以必须有个机制或者服务吧域名转换成 IP 地址。
DNS 服务就是用来解决这个问题的, 它提供域名到 IP 地址之间的解析服务。

HTTP在邂逅

HTTP协议特点

客户/服务器模式

客户/服务器模式工作的方式是由客户端向服务器发出请求,服务器端响应请求,并进行响应的服务。

简单快速

客户端向服务端请求服务时,只需要传送请求方法和路径。
请求方法有 GET、POST、PUT、TRACE、DELETE、HEAD、OPTIONS、CONNECT
由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。

灵活

虽然 HTTP0.9 的时候只能传输 HTML 文本,但是经过成长和发展后,HTTP 允许传输任意类型的数据对象。
正在传输的类型由 Content-Type 加以标记。

无连接

无连接的含义是限制每次连接只处理一个请求。
服务器处理完客户的请求,并收到客户的应答后,即断开连接。

HTTP协议产生于互联网 服务器需要处理上百万的网页访问 但是每个客户端与服务器交换数据的间歇性特别大,也就是说传输这个东西是有突发性、瞬时性的,并且网页浏览的联想性、发散性导致多次的传送数据的关联性很低,大部分的同道都是很空闲的,也就无端的占用了资源。
所以 HTTP 的设计者就有意把协议设计为,请求的时候连接,请求完就释放连接,尽快的将资源释放出来服务于其他的客户端。
当然随着时间的推移,网页变得越来越复杂所以就有了 Keep-alive。
Keep-alive,顾名思义保持存活,让客户端对服务器端的连接能够持续有效,可以避免建立连接或者重新建立连接。
但是 Keep-alive 会让原本可以释放的资源仍旧被占用,所以不能滥用它。

无状态

HTTP 协议是无状态的协议。
无状态是指协议对于事务处理没有记忆能力。
缺少状态意味着如果后续处理需要前面的信息,则它必须重新传输,这样可能导致每次连接传送的数据量增大。
服务器在不需要前置信息的时候它就应答的比较快。
那么在需要前置信息的时候该怎么办呢?所以两种用于保存 HTTP 连接状态的技术就诞生了 Cookie 和 Session。

HTTP报文结构

HTTP1.1 规范了总共 47 种报文头字段 HTTP 报文头大体上可以分为四大类:

  1. 通用报文头
  2. 请求报文头
  3. 响应报文头
  4. 实体报文头

通用报文头

可以用在请求报文也可以用在响应报文上

  1. Cache-control 控制缓存的行为
  2. Connection 连接的管理,逐跳首部
  3. Date 创建报文的日期时间
  4. Pragma 报文指令
  5. Trailer 报文末端的首部一览
  6. Transfer-Encoding 指定报文主体的传输编码方式
  7. Upgrade 升级为其他协议
  8. Via 代理服务器的相关信息
  9. Warning 错误通知

请求报文头

  1. Accept 用户代理可处理的媒体类型
  2. Accept-Charset 优先的字符集
  3. Accept-Encoding 优先的内容编码
  4. Accept-Language 优先的语言(自然语言)
  5. Authorization Web认证信息
  6. Expect 期待服务器的特定性为
  7. From 用户的电子邮箱地址
  8. Host 请求资源所在服务器
  9. if-Match 比较实体标记 ETag
  10. if-Modified-Since 比较资源的更新时间
  11. if-None-Match 比较实体标记(与 if-Matc 相反)
  12. if-Range 资源未更新时发送实体 Byte 的范围请求
  13. if-Unmodified-Since 比较资源的更新时间(与 if-Modified-Since 相反)
  14. Max-Forwards 最大传输逐跳数
  15. Proxy-Authorization 代理服务器要求客户端的认证信息
  16. Range 实体的字节范围请求
  17. Referer 对请其中 URI 的原始获取方
  18. TE 传输编码的优先级
  19. User-Agent HTTP 客户端程序的信息

响应报文头

  1. Accept-Ranges 是否接受字节范围请求
  2. Age 推算资源创建经过时间
  3. ETag 资源的匹配信息
  4. Location 令客户端重定向至指定 URI
  5. Proxy-Authenticate 代理服务器对客户端的认证信息
  6. Retry-After 对再次发起请求的时机要求
  7. Server HTTP服务器的安装信息
  8. Vary 代理服务器缓存的管理信息
  9. WWW-Authenticate 服务器对客户端的认证信息

实体报文头

  1. Allow 资源可支持的 HTTP 方法
  2. Content-Encoding 实体主体适用的编码方式
  3. Content-Language 实体主体的自然语言
  4. Content-length 实体主体的大小
  5. Content-Location 代替对应资源的 URI
  6. Content-MD5 实体主体的报文摘要
  7. Content-Range 实体主体的位置范围
  8. Content-Type 实体主体的媒体类型
  9. Expires 实体主体过期的日期时间
  10. Last-Modified 资源的最后修改日期时间

HTTP 请求方法剖析

HTTP1.1 常用的请求方法有:GET、POST、PUT、HEAD、DELETE、OPTIONS、TRACE、CONNECT

GET

GET 方法用来请求访问已被 URI 识别的资源。
制定的资源经过服务器端解析后返回响应内容。
也是浏览器默认的请求方法。
GET 方法也可以用来提交表单和其他数据。
例如:http://xxxxxx/xxxx.html?name=weilai&age=25
从上面的 URL 请求中很容易就可以辨认出表单的提交内容。
同时它还有长度限制,每种浏览器对其限制都是不同的,其中 IE 最短 IE 对 URL 长度的限制是 2083 字节(2K+35)。
GET 方法现在主要用于从服务器取出资源(一项或多项)。

POST

POST 方法与 GET 功能类似,一般用来传输实体的主体。
POST 方法的主要目的不是获取响应主体的内容。
POST 方法最初是 GET 方法的一个替代方法,它主要是想 Web 服务器提交表单的数据,尤其是一些大批量的数据。
POST 方法提交数据就不是直接写在 URL 上面了,而是直接写在请求体里面。 POST 方法现在主要用于在服务器新建一个资源。

PUT

PUT 方法与 POST 方法在用法上基本是相同的,都是用来提交参数的。
PUT 方法与 POST 方法最大的不同是;PUT 是幂等的;POST 是不幂等的。
PUT 方法现在主要用于在服务器更新资源(客户端提供改变后的完整资源)。 幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。
所以 PUT 方法多用于更新数据,POST 方法多用于创建数据。
但是 HTTP1.1 PUT 方法本身不带有验证机制的,任何人都可以上传文件,所以它是存在一定安全性问题的。

HEAD

HEAD 方法与 GET方法几乎是相同的,只不过 HEAD 方法返回的响应中没有具体的内容,主要用于获取报头。
HEAD 方法只是请求消息的报文头,而不是完整的内容。
HEAD 方法请求到的头部信息和使用 GET 方法请求到的头部信息是相同的。
所以利用这个 HEAD 方法我们就不必要去传输整个的内容就可以得到我们想要请求的那个 Request URI 所标识的资源信息。
所以 HEAD 方法经常会用来测试某些超链接的有效性。

DELETE

DELETE 方法与 PUT方法是相反的。
DELETE 方法主要是根据我们请求的 URI 去删除服务器指定的资源。
但是 HTTP1.1 DELETE 方法本身不带有验证机制的,任何人都可以删除文件,所以它是存在一定安全性问题的。

OPTIONS

OPTIONS 方法是用来查询针对请求 URI 指定的资源支持的方法。
一般用在,当我们不知道对方支持什么请求方法去询问的。
当涉及跨域资源共享(CORS)的时候,非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。

TRACE

TRACE 方法回显服务器收到的请求,主要用于测试或诊断。
客户端可以通过 TRACH 方法查询发送出去的请求是到底怎么样被加工修改的,或者说是篡改的;这是因为请求请求想要连接原目标服务器的时候,可能会通过代理中转, TRACH 方法就是用来确认连接过程中发生的一系列的操作,看看中转的过程。
TRACE 方法特别容易引发 XST(跨站追踪) 攻击。

CONNECT

CONNECT 方法可以开启一个客户端与所请求资源之间的双向沟通的通道,它可以用来创建隧道。