最近部门组织了一次前端性能优化交流会,大家从输出页面 URL 到最终页面展现内容这个过程提出了许多优化点。但同时发现很多同学对 HTTP 协定层的常识不能串联起来,于是整顿了这篇文章,心愿能够给大家带来一丝灵感。
当咱们在页面上发动一个 AJAX 申请的时候,在网络协议层面都经验了哪些内容?
// 发动申请
fetch('https://baidu.com')
// 协定层 1...
// 协定层 2...
// 协定层 3...
.then(res=>
// 失去后果
console.log(res)
})
如上述代码所示,咱们对 baidu.com
发动了一个网络申请,最终在 then 办法中失去了具体的响应内容。
应用 Wireshark 抓包后果如下:
图中能够看到,申请 baidu.com 时,首先通过 TCP 3 次握手建设连贯,而后通过 HTTP 传输内容,最初通过 TCP 4 次挥手断开连接。
实在的过程更加简单,咱们次要剖析以下几点:
-
建设连贯阶段
- DNS 域名解析(应用层)
-
建设 TCP 连贯(传输层)
- 通过 IP 寻址找到指标服务器(网络层)
- 通过 Mac 寻址找到服务器硬件接口(数据链路层)
- 通过网线向服务器硬件接口传输比特信息(物理层)
-
发送数据阶段
- 建设 SSL 平安连贯(应用层)
- 发送 HTTP 申请(应用层)
建设连贯阶段
要获取 baidu.com 的网页内容,就须要和 baidu 服务器建设连贯,怎么建设这个连贯呢?
- 通过 DNS 获取 baidu 的 IP 地址。
- 建设 TCP 连贯。
DNS 域名解析
通过 DNS 解析,咱们就能找到 baidu 服务器对应的 IP 地址。
如图:
通过 DNS 解析后,咱们就能失去 baidu.com 的 IP 地址了:39.156.69.79 和 220.181.38.148,通常客户端会随机选中一个 IP 地址进行通信。
域名的解析步骤
其实 IP 不肯定要通过 DNS 解析能力获取,它通常会被客户端缓存,只有在 DNS 缓存都没有命中的时候才会申请 DNS 服务器。
判断步骤如下:
- 判断浏览器是否有缓存 IP 地址。
- 判断本机是否有缓存该 IP 地址,如:查看 Host 文件。
- 判断本地域名解析服务器是否有缓存 IP 地址,如:电信,联通等运营商。
- 向 DNS 根域名解析服务器,解析域名 IP 地址。
- 向 DNS 二根域名解析服务器,解析域名 IP 地址。
- 以此类推,最终取得 IP 地址。
建设 TCP 连贯
有了 IP 地址之后,客户端和服务器端就能建设连贯了,首先是建设 TCP 连贯。
TCP 是一种面向连贯的、牢靠的 、基于 字节流 的传输层通信协议。
在这一层,咱们传输的数据会依照一个个的字节装入报文中,当报文的长度达到最大分段(MSS)时,就会发送这个报文。如果传输的报文很长,可能会被拆分成多个 TCP 报文进行传输。
TCP 报文头如下:
咱们次要看以下几点:
- 源端口、目标端口。
- 序列号:seq,报文的惟一标识。
- 确认号:ack,报文的确认标识,便于确认 seq 是否曾经收到。
-
TCP 标记:
- SYN 为 1 示意这是连贯申请或是连贯承受申请。用于创立连贯和同步序列号。
- ACK 为 1 示意确认号字段无效。留神这里大写的 ACK 只是一个标记,和确认号 ack 并不相同。
- FIN 为 1 示意要求开释连贯。
- 窗口:示意发送方能够接管的字节数,即接管窗口大小,用于流量管制。
接下来,咱们看一下 TCP 是怎么建设连贯的?
如图所示,建设 TCP 连贯须要 3 个步骤,俗称三次握手。
- 第一次握手:客户端向服务器端发送序列号 seq=x 的标识,示意开始建设连贯。
-
第二次握手:服务器端回发一个 ack=x+1 的标识,示意确认收到第一次握手,同时发送本人的标识 seq=y。
- 客户端确认本人收回的数据可能被服务器端收到。
-
第三次握手:客户端发送 ack=y+1 的标识,标识确认收到第二次握手。
- 服务器端确认本人收回的数据可能被客户端收到。
通过了 3 次握手,即保障了客户端和服务器端都能失常发送和接收数据,TCP 连贯也就建设胜利了。
TCP 牢靠传输原理
上文中说到,TCP 是牢靠的传输,这是为什么呢?
这是因为 TCP 外部应用了 进行期待协定 ARQ,它通过 确认 和 重传 机制,实现了信息的牢靠传输。
例如:
- 客户端发送数据 M1
- 服务器端确认数据 M1 收到
- 客户端发送数据 M2
- 服务器端确认数据 M2 收到
- 顺次类推 …
在这期间,如果某一条数据很久都没有失去确认,客户端就会重传这条数据。这样一来,对于与每一次发送的数据,服务器端都失去了确认,即保障了数据的可靠性。
尽管 ARQ 能够满足数据可靠性,但每次只能发送和确认一个申请,效率太低了,于是就产生了间断 ARQ 协定。
间断 ARQ 协定 会间断发送一组数据,而后再批量期待这一组数据的确认信息,好比把单线程 ARQ 变成了多线程,大大提高了资源的利用效率。
如:
- 客户端发送数据 M1、M2、M3、M4。
- 服务器端确认数据 M4 收到,示意 M4 及之前的数据都收到了。
- 客户端发送数据 M5、M6、M7、M8。
- 服务器端确认数据 M8 收到,示意 M8 及之前的数据都收到了。
在这个流程中,服务器端不须要对每一个数据都返回确认信息,而是接管到多个数据时一并确认,这个形式叫做 累计确认。
这里有个疑难,TCP 的每一次握手,是怎么找到目标服务器呢?
答:通过 IP 协定。
依据 IP 协定找到指标服务器
IP 协定的目标是实现网络层的数据转发,它通过路由器一直跳转,最终把数据胜利送达目的地。
上文中的每一次 TCP 握手以及数据交互,都是通过 IP 协定去传输的。
IP 报文头如下:
咱们关注以下两点就能够了:
- 源 IP 地址
- 目标 IP 地址
发动一个 IP 申请执行流程如下:
- 构建 IP 申请头(源 IP、指标 IP)。
- IP 协定通过算法,计算出一条通往服务器端的门路。
- 发送端查问路由表,找出下一跳的 IP 地址(通常是路由器),并发送数据。
- 路由器查问路由表,找出下一跳的 IP 地址,并发送数据。
- 一直反复步骤 4,直到找到目标局域网。
- 发送数据。
路由表存在于计算机或路由器中,由目标 IP 地址、子网掩码、下一跳地址、发送接口四局部组成。通过目标 IP 地址,即可找到下一跳的地址,进行转发。
例如:A 要向 G 发送 IP 数据。
具体流程如下:
-
A 生成 IP 头部(源 IP:A,目标 IP:G)
- A 查问路由表,发现下一跳为 B,于是把数据传给 B。
-
B 生成 IP 头部(源 IP:A,目标 IP:G)
- B 查问路由表,发现下一跳为 E,于是把数据传给 E。
-
E 生成 IP 头部(源 IP:A,目标 IP:G)
- E 查问路由表,发现下一跳为 G,于是把数据传给 G。
- 达到目的地 G。
你是否有纳闷,为什么 IP 会依照这条门路向 G 传输数据呢?
其实,上图中的门路并非只有一条,咱们通过 ABEG 达到了目的地 G,同样也能够通过 ABCFHG 达到 G,这两种门路都能实现工作,为什么 IP 不抉择 ABCFHG 这条门路呢?
这就波及到了 IP 寻址的算法。
IP 寻址算法
咱们能够把网络中的所有计算机都看做是一个点,计算机之间的连贯看做是一条线,这些点和线就组合成了一个图。
例如:
通过上图,咱们就把简单的网络转化成了数学问题。IP 寻址算法,其实就是图论中的最短门路的算法。
最短门路算法在 IP 协定中有 2 种实现:
-
RIP 协定
- 应用间隔矢量算法,确保 IP 路由跳转的次数最小。
-
原理
- 每个节点中都保留有其余节点的地位信息(跳数和下一跳的 IP)。
- 通过和街坊节点进行数据交换,更新本人到目的地的最短距离,一直反复,即可失去终点到起点的最短门路。
- 实现简略,开销很小,实用于小型网络。
-
OSPF 协定
- 应用迪杰斯特拉算法,确保 IP 路由跳转的速度最快。
-
原理
- 从起始点开始,采纳贪婪算法的策略,每次遍历到始点间隔最近且未拜访过的顶点的邻接节点,直到扩大到起点为止。
- 实用于大型网络。
通过以上两个协定,咱们就能找到通往目的地的门路了。
这里抛出一个问题:IP 数据是怎么从一个路由器跳到另一个路由器呢?
答:通过以太网协定。
通过 Mac 寻址找到服务器硬件接口
IP 协定次要是用来寻找最优门路的,具体的传输是由以太网协定来做的。
以太网属于数据链路层,它次要负责相邻设施的通信。原理是通过查问交换机 Mac 表,找到通信单方的物理接口,进而开始通信。
以太网报文头如下:
咱们只用关怀以下 3 个点:
- 源 Mac 地址
- 目标 Mac 地址
- 校验码 CRC:校验以后帧是否无效。
能够看到,以太网层都是通过 Mac 地址进行通信的,这里的 Mac 地址是哪里来的呢?
答:通过 ARP 协定。
ARP 协定 是一个通过解析 IP 地址来找寻 Mac 地址的协定。IP 地址转换成 Mac 地址后,就能进行以太网数据传输了。
例如:
当机器 A 向机器 C 发送数据时:
- A 构建以太网报文(源地址:A,目标地址:C),并通过网卡收回数据帧。
- 数据帧达到交换机 B,交换机取出目标地址 C 的 Mac 地址。
-
B 查问 Mac 表,依据目的地 Mac 地址,匹配 C 的硬件接口。
- 如果找到 C 的硬件接口,发送数据。
- 如果未找到 C 的硬件接口,向 B 直连的所有机器发送播送信息找 C,找到后会把 C 记录到 Mac 表中。
通过上述的流程,咱们就找到了目标机器的硬件接口。
通过以太网协定,咱们找到了指标机器的硬件接口,接下来要怎么发送信息呢?
答:通过物理层。
通过网线向服务器硬件接口传输比特信息
在没有 WiFi 的年代,咱们只能通过插网线来进行上网,网线其实就是物理层的设施之一。
网线能够由多种资料组成,最常见的就是光纤和电缆。
光纤和电缆的传输原理相似,都是通过两个信号来模仿二进制数据的,一个信号即为一个比特。
- 电缆中:高电位示意 1,低点位示意 0。
- 光纤中:光洁示意 1,光燃烧示意 0。
如:在光纤中,咱们通过观察光的闪动,即可得悉传输的二进制数据。
有了这些物理设施,咱们就能把简单的数据转换成光信号或者电信号进行传输了。
发送数据阶段
发送数据能够分为两个步骤:
- 建设平安层 SSL
- 发送 HTTP 申请
建设平安层 SSL
本文的案例是发送一个 HTTPS 的申请,所以在发送数据之前,会创立一个 SSL 平安层,用于数据加密。
通常的加密办法有两种:
-
非对称加密
- A 有钥匙,B 没有钥匙,且他们都有一个公共的锁,B 给 A 发送数据时,都会先把数据锁起来再发送。
- 接收数据时,A 用钥匙解开锁,即可失去数据。除 A 以外,其他人没有钥匙,也就获取不到数据。
- 实现了单向通信加密。
-
对称加密
- A、B 单方都有一把雷同的钥匙和一个公共的锁,每次发送数据时,都把数据放在锁里进行发送。
- 接收数据时,A、B 单方就用各自的钥匙来解锁。其他人没有钥匙,也就获取不到数据。
- 实现了双向通信加密。
互联网通信是双向的,所以咱们须要应用对称加密,可是,怎样才能保障通信单方都有一把雷同的钥匙呢?
目前的解决方案:
- 先应用非对称加密,进行秘钥协商,让通信单方拿到雷同的钥匙。
- 而后应用对称加密,进行加密传输。
秘钥协商过程如图:
图中划重点:
- 客户端发送本身反对的加密算法。
- 服务器端抉择一种加密算法,同时返回数字证书。
- 客户端确认证书无效。
- 客户端生成随机数,并应用证书中的服务器公钥加密,而后发送给服务器。
- 服务器端应用私钥解密,取得随机数。
- 单方应用第 2 步确定的加密算法,把随机数进行加密,即可取得雷同的对称加密秘钥。
Ok,秘钥协商之后,咱们的 SSL 平安层也就建好了。
秘钥协商时存在一个问题:
秘钥协商时,怎么保障是和真正的服务器在协商,而不是一个中间人呢?
答:数字证书。
数字证书重点关注 2 个局部:
- 服务器公钥
- 数字签名
其中,数字签名又是由服务器公钥和证书私钥加密生成的,目标是为了避免服务器公钥被篡改。
有了数字证书,客户端就能通过验证证书,来判断服务器是否是真正的服务器了。
验证逻辑如下:
能够看到,数字证书通过同样的算法进行解密,如果失去雷同的信息摘要,就能保证数据是无效的,如果不统一,则会验证失败,回绝后续的申请。
到这里为止,所有的筹备工作都就绪了,接下来才是发送 HTTP 申请。
发送 HTTP 申请
HTTP 协定其实就是制订了一个通信规定,规定了客户端和服务器之间的通信格局。
以申请 baidu 首页为例:
如上图所示,发动 HTTP 申请时,必须恪守以下规定:
- 申请办法(必填)
GET
- 申请地址(必填)
/
- HTTP 协定版本(必填)
1.1
- 其余 HTTP 头部字段(可选)
Host
、User-Agent
、Accept
- 申请参数,放在空行前面(可选)
服务器响应申请时,同样恪守了 HTTP 响应规定:
- HTTP 协定版本(必填)
1.1
- 响应状态码(必填)
200
- 状态码形容(必填)
OK
- 其余 HTTP 头部字段(可选)
Date
、Server
、ETag
、Last-Modified
等 - 申请参数,放在空行前面(可选)
只有咱们恪守这个规定,就能进行 HTTP 通信了。
到目前为止,咱们曾经剖析实现了数据申请的所有过程,你是否都了解了呢?
思考与总结
本文通过一个网络申请,对整个 HTTP、TCP、IP、以太网等协定进行了流程化剖析,最初再梳理一下:
- 申请 baidu.com。
- DNS 解析 baidu.com,失去 IP 地址。
- 建设 TCP 连贯。
- IP 协定通过算法,计算出一条通往服务器最优门路。
- IP 沿着门路跳转时,会通过 ARP 协定把 IP 地址转换成 Mac 地址。
- 以太网通过 Mac 地址,找到通信单方的硬件接口。
- 物理层通过网线作为载体,在两个硬件接口之间传输比特信号。
- TCP 连贯建设结束。
- 建设 SSL 平安层。
- 发送 HTTP 申请。
最初,如果你对此有任何想法,欢送留言评论!