前端需了解的HTTP知识

前端需了解的网络知识

HTTP 版本发展过程

HTTP1.0

● 新增了 POST 请求方式
● 新增了请求头、http 状态码
● 新增了 cookie

HTTP1.1

● 新增了 keep-alive 长连接
● 新增了 pipeline 管道
● 新增了 PUT、DELETE、OPTIONS、PATCH 等新的请求方式

HTTP2.0

● 头部支持二进制协议、支持头部压缩
● 新增了多路复用

HTTP1.1 有哪些特点

● 默认开启了长连接 Connection: keep-alive,TCP 连接复用,可以被多个请求服用,避免了连接建立和释放带来的开销。
● 支持 pipeline 管道传输,可以不必等待请求响应了才能发起下一个请求,但是响应的时候必须按照发送顺序接收,一旦有一请求个丢包了,后面的都会被卡住。
● 并发连接:浏览器会同时和服务器建立多个 TCP 连接,在同一个 TCP 连接上顺序处理多个 HTTP 请求。
● 增加了 PUT、DELETE、OPTIONS、PATCH 方法
● 新增了一些缓存字段(If-Modified-Since、If-None-Match)
● 请求头引入 range 字段,支持断点续传
● 允许响应数据分块(chunked),利于传输大文件

HTTP2.0 有哪些特点

● 二进制协议:HTTP1.1 版本的头部信息是文本,数据部分可以是文本也可以是二进制。HTTP2 版本的头部和数据部分都是二进制,且统称为“帧”。
● 多路复用:HTTP1.1 使用 pipeline 管道机制,虽然可以同一个 TCP 发多个请求,但是响应的顺序要和请求的顺序一致,一旦某个请求响应嘎了,那后面的响应客户端接收不到,这就是“队头阻塞”问题。HTTP2.0 采用多路复用,就不用按照顺序来,避免了“队头阻塞”的问题。
● 头部信息压缩:使用算法压缩头部,减少数据传输量。
● 服务端主动推送:允许服务端主动向客户端推送数据。
● 数据流:服务器以流的 stream 的形式向客户端返回内容。

HTTP3.0 有哪些特点

首先 HTTP 是基于 TCP 协议实现的。
TCP 主要的作用是以正确的顺序将整个字节流从一个端传输到另外一个端(服务端->客户端),当流中的某些数据包丢失了,导致后续的数据包没有按顺序到达一端,服务端就要那就要等 TCP 需要重新发送这些丢失的数据包,等到所有的数据包到了另一个端的时候才会被 HTTP 处理,这被称为TCP 队头阻塞问题。
注:HTTP2.0 多路复用解决的是 HTTP 队头阻塞问题。

HTTP3.0 就是为了解决 TCP 队头阻塞问题,发明了一个基于 UDP 协议的 QUIC 协议,特征就是快。
HTTP 是基于 TCP 协议的,TCP 建立连接是需要三次握手的。
QUIC 是基于 UDP 协议的,它不需要三次握手,减少时间延迟。

所以来看 HTTP3.0 主要是:
● 使用了 UDP 协议,不需要建立三次握手,缩短了 HTTPS 建立连接的时间
● 解决了队头阻塞问题,TCP 传输过程中,某个数据包丢失了,后续数据包就会被接收端一直保持着,直到丢失的数据包重新发送并到达了接收端为止,这种情况就导致了后续数据包延迟传输,就是为了保证按照发送的顺序来接收数据。

HTTP2.0 为什么要使用分帧层

参考文章

● 二进制协议比文本协议更紧凑,减少占用空间。
● 分帧层相当于把 HTTP 切分了,更加灵活。
● 分帧层有着属于自己的报文头,其中的 Stream Identifier 使得操作系统具备将多个响应以及请求一一匹配的能力,这个是 http/2 性能提升的关键,也就是多路复用。

什么是长连接?keep-alive

TCP 每次连接都要经历三次握手,而每次发请求和响应都要重新建立连接,开销很大。
如果开启了长连接,就可以避免,只需要三次握手一次,就可以进行多次请求和响应。

长连接

什么是 Pipelining 管道传输

可以同时发送多个请求,不需要等有结果了才能发第二个请求,但是响应结果必须和发请求的顺序一致,一旦出现某个请求丢包了(网络问题等),就会导致后面的请求卡住。

pipeline 管道传输和 HTTP2.0 多路复用的区别

注:pipeline 技术是基于长连接。

首先看一下,有没有 pipeline 的区别

● 没有使用 pipeline,每次发一条请求,必须要收到响应,才能发下一条请求。
● 使用了 pipeline,可以发多条请求,但是收到的响应顺序必须是和发的顺序是一致的,一旦某条响应数据卡住了(网络原因等问题),就会导致后面的响应数据都被卡住了,这就是“队头阻塞”问题。

HTTP2.0 多路复用是怎么处理的?

● http2.0 全面采用二进制分帧形式,假如请求 1 需要收到响应的数据是【1-1,1-2,1-3】,没有多路复用的话,那么收到的必须是完整且有顺序的【1-1,1-2,1-3】这样才算结束。有了多路复用结束过后,我们收到的数据可以不需要完整和有序,收到的数据 1-1,2-1,1-2,3-1,1-3,2-2,最后 http 会自己把数据组装成【1-1,1-2,1-3】交给请求 1。一句话概括:收到的数据不需要和发出去的顺序一致。

浏览器 http 请求的并发性是如何体现的?并发请求的数量有没有限制?

页面资源请求的时,浏览器会同时和服务器建立多个 TCP 连接,在同一个 TCP 连接上顺序处理多个 HTTP 请求。所以浏览器的并发性就体现在可以建立多个 TC 连接,来支持多个 HTTP 同时请求。

谷歌浏览器最多允许对同一个域名建立 6 个 TCP 连接。

一个 TCP 连接可以同时发送几个 HTTP 请求?

一般来说单个 TCP 连接,同一时间只能处理一个 HTTP 请求,虽然我们知道 HTTP1.1 有个 Pipelining 管道机制,可以同时发多个请求,实践中存在很多问题(响应的顺序和请求的顺序保持一致,如果响应的时候有一个请求嘎了,那后面的响应都会丢失),所以浏览器默认是关闭的,因此可以认为是不支持同时发多个请求的。
HTTP2 提供了多路复用,可以同时在同一个 TCP 连接上发多个 HTTP 请求。

TCP 和 UDP 区别

● TCP 是面向连接,提供可靠的服务,UDP 是无连接的,发送数据前是不需要建立连接,UDP 尽量最大交付,但是不保证可靠交付。
● UDP 具有较好的实时性,工作效率比 TCP 高。

UDP 应用场景:直播、游戏
TCP 应用场景:网页

● TCP 连接只能一对一,一个客户端对应一个服务端,UDP 可以一对一,一对多,多对一,多对多的交互通信
● TCP 是面向字节流的,将数据包一点一点传递给另外一个端,UDP 是面向报文的一次交付一个完整的报文。

TCP 三次握手

TCP 是面向连接的,在使用 TCP 前必须要建立连接,而建立连接是通过三次握手来进行的,过程如下:

三次握手、四次挥手

● 第一次握手:客户端发送 SYN 包(SYN = x)到服务器,并且进入 SYN_SENT 状态,等待服务器确认
● 第二次握手:服务器收到 SYN 包,必须确认客户端的 SYN 包(ACK = x + 1),同时自己也发送一个 SYN 包(SYN = y),即发送给客户端的就是(SYN + ACK)包,此时服务器进入 SYN_RECV 状态(receive)
● 第三次握手:客户端收到了服务端的 SYN + ACK 包,向服务器发送确认包(ACK = y + 1), 发送完毕过后,客户端和服务端就进入 ESTABLISHED 状态。

为什么要三次握手

主要是为了建立可靠的通信,目的就是双方确认与对方发的发送和接收是正常的。假如只有两次握手,那么服务端就不知道客户端是否具有接收数据的能力。

TCP 四次挥手

参考文档:

流程图如上
四次握手分析如下:

  1. 客户端发送 FIN 包(FIN = x + 2)和 ACK(ACK = y + 1)到服务器,告诉服务器我需要关闭连接,此时处于半关闭状态(FIN-WAIT-1)。(此时还是可以接受服务端传过来的数据)。
  2. 服务器收到 FIN 包和 ACK 包后,发送一个 ACK(ACK = x + 3)针对上一次 FIN 的回应给客户端,好的我收到,我还有数据没传完,要等一下,此时服务器进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态
  3. 过了一会,再给客户端发送一个 FIN(FIN = y + 1),表示服务端的数据都发送完了,释放连接。服务器结束 CLOSE-WAIT 状态,进入 LAST-ACK 状态。
  4. 客户端收到客户端的 FIN(FIN = y + 1),确认了服务端做好了释放连接的准备,于是结束 FIN-WAIT-2 状态,进入 TIME-WAIT 阶段,并向服务端发送 ACK 包(ACK = y + 2)表示可以释放连接了。
    随后客户端在 TIME-WAIT 阶段等待 2MSL,等服务端收到客户端的 ACK 包过后,服务端就进入 CLOSED 阶段,正式关闭连接。客户端 2MSL 后也进入 CLOSED 阶段。

第二次和第三次挥手为什么要分开?为什么要合并?

为了数据传输的完整性,第一次挥手,服务端收到断开连接的请求,但是很有可能服务端的数据还没有传完,要过一会,等所有数据都传完,服务端才能断开连接。

第四次挥手发送完最后一个报文,为什么不直接进入关闭状态?而是要进入等待时间,2MSL 后才进入关闭状态?

最后一次挥手完成过后,客户端并不知道服务端有没有接收到,很有可能存在网络出现问题,导致 ACK 报文没有接收到,服务端会重新发送 FIN,客户端会再次发送 ACK,TIME-WAIT 的 2MSL 使用来重发可能丢失的 ACK 报文的。

为什么要四次挥手

是因为服务端 FIN 断开连接和 ACK 确认接受报文是分别在两次挥手中传输的。是为了保证服务端传递数据的完整性。先回复给客户端我这边已经收到释放连接的请求(发送 ACK 包),但是要过一会,等数据都传输完毕,完毕过后过后告诉客户端传输完成了,我可以关闭了(发送 FIN 包)

HTTPS 加密过程

前置知识
对称加密:只有一把钥匙,既可以加密也可以解密。
非对称加密:有两把钥匙,一把钥匙用于加密(公钥),一把钥匙用于解密(私钥)。

加密过程

  1. 客户端发起一个 http 请求
  2. 服务端返回一个数字证书给客户端(证书包含公钥、网站地址、证书颁发机构、失效日期等)。证书里面有一个公钥用来加密信息的,服务端持有一个私钥用来解密的。
  3. 客户端收到证书后,会先验证证书的合法性(证书包含的地址和正在访问的地址是否一次,是否过期)。
  4. 验证通过后,客户端随机生成一个对称密钥(随机字符串),然后用公钥进行加密,传给服务端进行解密,服务端就可以拿到这个对称秘钥。
  5. 上一步客户端和服务端都拥有了一个对称秘钥(随机字符串),后续的传输内容都根据这个秘钥来进行对称加密。

https 是绝对安全的吗?

有一种攻击手段叫做中间人攻击。
通俗一点描述:这个中间人对浏览器冒充服务器,对服务器冒充浏览器。这样就可以拿到通信数据了,并且可以篡改。

中间人攻击流程

分析过程:

  1. 浏览器发请求,申请获得证书。
  2. 服务端返回一个数字证书给客户端(证书包含公钥 A、网站地址、证书颁发机构、失效日期等)。
  3. 但是直接被中间人拦截了,截取了公钥 A,然后中间人自己生成了一个公钥 B,并发送给客户端。
  4. 客户端生成一个对称密钥 X(随机字符串),并用公钥 B 进行加密,发送给服务端,此时被中间人拦截了,并且用公钥 B 解密,因此可以得到对称秘钥 X。
  5. 然后中间人中公钥 A 加密对称秘钥 X,给服务端,后端的通信都是通过这个对称秘钥 X 进行对称加密。