前端的一些http知识

1,209

一些http知识

前置知识

首先放一张非常经典的计算机网络

关于五层结构 「物理层」「数据链路层」「网络层」「运输层」「应用层」我们依次来讲

我们拿wireshark 抓个http包看一下就能明白各层的区别

Screen Shot 2020-02-10 at 12.11.06 PM.png

物理层

只有在网线(光纤)中传递的bits

数据链路层

就有源mac 地址 和下一跳的mac 地址了(相当于网络设备的物理地址)

从图中看 源 d4:ee:07:69:fb:b0 到目的 98:01:a7:ae:c3:0d

源是我家的路由器,验证一下 终端输入 arp -a

Screen Shot 2020-02-10 at 12.27.35 PM.png

192.168.199.1 的地址默认是局域网内路由器的IP,右边就是 d4:ee:07:69:fb:b0 路由器 mac 地址了

对应的 终端输入 ifconfig

Screen Shot 2020-02-10 at 12.30.59 PM.png

en0下 ether 98:01:a7:ae:c3:0d 就是我们电脑网卡的mac 地址了

对应的arp 就是数据链路层的协议了

网络层

就有源ip 地址和 目的ip 地址了

常用的协议 ICMP,基本实现 ping 命令

传输层

增加对应的端口了 比如上层协议 http 在 传输层 协议上端口是 80, https是 443,对应的还会增加数据包的概念,例如 seq 数据包传输序列,acq 收到消息回执等一系列报文内容

常用的协议 tcp, udp

应用层

应用层大家就特别熟悉了 以http示例,会增加自定义的报文内容了,比如host acept之类的request的请求头,大家应该很清楚了

常用的协议: http https

https

我们在前面看到http的传输都是明文传输,如果有个坏蛋在路由器中植入一段恶意程序,把你的「数据包取出来转发给其他网络」那就很危险,为了提高网络安全性,引入https概念,为了避免http明文传输,https 在 传输层与应用层 增加了一层加密层 ssl,我们看一下具体的实现,首先也科普一些基础的https相关的知识

  • 加密算法,非对层加密算法 rsa , 由一个共钥和私钥组成,一般拿公钥加密的数据包只能拿私钥解开,举个最简单的加密例子,两个足够大的素数作为公钥,素数相乘的结果作为私钥,你拿着私钥基本取不出公钥,因式分解解不出来呀

  • 证书,证书的颁发一般来自一个负责发放和管理数字证书的权威机构,证书会以RSA将你的公钥用它的私钥加密起来,对应的你的操作系统里已经集成了解密证书的公钥,所以是权威机构颁发的证书,你是一定能够取到公钥的

我们具体看一下ssl层 握手的过程(ssl 层实现协议 tls)

Screen Shot 2020-02-10 at 12.58.54 PM.png

我们来分析一下这个过程:

首先我们的主机向目的主机发了一个client hello 包

这个包包含

Screen Shot 2020-02-10 at 1.02.07 PM.png

随机数1 Random 以及 SSL Version 等信息 之后server向我们源主机发了一个server hello Certificate 等包含信息的多个包

Screen Shot 2020-02-10 at 2.28.28 PM.png

其中 server hello 包含 第二个随机数 Random2

Screen Shot 2020-02-10 at 2.37.24 PM.png

Certificate 为服务端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥

Screen Shot 2020-02-10 at 2.38.50 PM.png

Server Key Exchange DH算法,客户端发送服务器使用的DH参数(DH 是对称加密算法,剧透一下,DH 算法就是利用前面传递的Random随机数生成对称密钥)

Screen Shot 2020-02-10 at 2.42.25 PM.png

Server Hello Done 通知客户端 Server Hello 过程结束

Screen Shot 2020-02-10 at 2.45.36 PM.png

之后客户端会发送服务端一个包含Client Key Exchange Change Cipher Spec等包含信息的多个包

Screen Shot 2020-02-10 at 2.52.44 PM.png

Client Key Exchange,其中Pubkey 为客户端生成的随机数 Random3 用服务端传送过来证书中的公钥加密的,学术语叫Premaster key 感兴趣的同学可以看看DH算法,服务端可以用私钥解密,至此服务端和客户端都拥有 Random1 Random2 Random3了,可以通过DH算法生成一个对称的密钥了

Screen Shot 2020-02-10 at 3.07.37 PM.png

Change Cipher Spec,其中客户端通知服务端后面再发送的消息都会使用前面协商出来的密钥加密了,是一条事件消息。

Screen Shot 2020-02-10 at 3.13.27 PM.png

Encrypted Handshake Message,其中客户端发出第一条加密消息。服务端接收后会用密钥解密,能解出来说明前面协商出来的密钥是一致的

Screen Shot 2020-02-10 at 3.15.17 PM.png

之后服务端会发送客户端一个包含Change Cipher Spec Encrypted Handshake Message等包含信息的多个包

Screen Shot 2020-02-10 at 3.17.02 PM.png

Change Cipher Spec:这一步对应于之前的事件消息,服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息

Encrypted Handshake Message:对一步对应于之前的加密消息,服务端发出第一条加密消息。客服端接收后会用密钥解密,能解出来说明前面协商出来的密钥是一致的

如果验证失败:断开链接,握手失败

经典tcp三次握手

最后提一下经典的tcp三次握手吧,有上面的分析经验后,tcp相信相对来说就会很简单了

Screen Shot 2020-02-10 at 3.51.30 PM.png

其中SYN 和 ACK 为标志位信息,标志位一共有6种,常用的分别为:

Screen Shot 2020-02-10 at 3.43.36 PM.png

  • SYN表示建立连接
  • FIN表示关闭连接
  • ACK表示响应
  • PSH表示有 DATA数据传输
  • RST表示连接重置

第一步:其中源主机向目的主机发起链接 标志位 SYN 发送一个seq 0序列的包 第二步:目的主机向源主机发起链接 标志位 SYN ACK ack = 0 + 1 发送一个seq 0序列的包 第三步:源主机发包 标志位 ACK ack = 0 + 1

握手成功!!!

http2

http2 是 http的新型协议,具有报文头部压缩,多路复用的特点。

http 1协议是串行的,一个请求发起必须再上一个请求结束后才能发起,为了提高效率,chrome 支持并行6个,即chrome 会开6个线程,分别做tcp 握手,数据传输,由于我们一般会打开请求头的keep-live 所以这6个tcp链接不会断开

http2 的多路复用则可以并发多个请求,没有之前6个的限制,来张图对比

http1:

Screen Shot 2020-02-10 at 4.00.59 PM.png

http2:

Screen Shot 2020-02-10 at 4.01.05 PM.png

http2已经出来5年了,主流浏览器均已支持,看一下详细情况

Screen Shot 2020-02-10 at 4.04.19 PM.png

nginx 的修改也异常简单:listen 443 ssl http2

如果nginx 不支持 http2 怎么办?别担心

Screen Shot 2020-02-10 at 4.22.03 PM.png

在ssl 那层握手的时候 client hello 的时候 会将h1和h2协议都带上,会和nginx “negotiate”

Screen Shot 2020-02-10 at 4.24.01 PM.png

上图中的结果就是,我们使用h1吧

和浏览器的结合

tcp 握手耗时是橘黄色的耗时,紫色是ssl 握手的耗时

Screen Shot 2020-02-10 at 4.27.17 PM.png

如果你想统计浏览器握手耗时的话,可以借助performance API

Screen Shot 2020-02-10 at 4.31.12 PM.png

time = requestStart - secureConnectionStart

把performance 的resource 挨个累加就好了