让我们思考一个问题,你在浏览器中输入 : www.baidu.com 的时候,在你按下回车的那一瞬间,发生了什么事情,为什么能够在你按下之后,就能将百度的首页返回?
“ WC,很简单啊,就是发送一个请求然后就获取了呗~” emmmm,很简洁的答案。那么具体是为什么呢?直到我看了阮一峰的互联网协议入门(一)之后,才明白原因。耐心的小伙伴可以去看一看阮一峰的教程。如果是想简单知道,那么就继续往下看哈~
所谓的网络通信就是交换数据包。电脑 A 向电脑 B 发送一个数据包,后者收到了,回复一个数据包,从而实现两台电脑之间的通信。那么发送这个包,需要知道两个地址:
-
对方的 MAC 地址
-
对方的 IP 地址
有了这两个地址,数据包才能准确送到接收者手中。但是,MAC 地址有局限性,如果两台电脑不在同一个子网络,就无法知道对方的 MAC 地址,必须通过网关转发。
好了,看到这,就有人想要问了,什么是 MAC 地址?根据以太网规定,连入网络的所有设备,都必须具有"网卡"接口。数据包必须是从一块网卡,传送到另一块网卡。网卡的地址,就是数据包的发送地址和接收地址,这叫做 MAC 地址。每块网卡出厂的时候,都有一个全世界独一无二的 MAC 地址,长度是 48 个二进制位,通常用 12 个十六进制数表示。
什么?你仿佛在逗我,我只知道我自身网卡 MAC 地址,我怎么知道他的网卡 MAC 地址?
根据 ARP 地址解析协议,就可以解决这个问题,这里只需要知道,以太网数据包必须知道接收方的 MAC 地址,然后才能发送
🎺 ARP 地址解析协议,实现由 IP 地址得到 MAC 地址,每个主机都有一个 ARP 高速缓存,高速缓存中存放着一个在 IP 地址到硬件地址 MAC 的映射表,并且这个映射表还经常动态更新
如果主机 A 知道主机 B 的 IP 地址,但是 ARP 高速缓存中没有该 IP 地址到 MAC 地址的映射,此时主机 A 通过广播的方式发送 ARP 请求分组,主机 B 收到该请求后会发送 ARP 响应分组给主机 A 告知其 MAC 地址,随后主机 A 向其高速缓存中写入主机 B 的 IP 地址到 MAC 地址的映射
⚠️ ARP 是解决了在同一个局域网上的主机或路由器 IP 地址和硬件地址之间的映射问题,如果不在一个局域网上,就无法解析出另一个局域网上另一主机的硬件地址
emmmm,那我知道了他的 MAC 地址,我该怎样才能把数据包准确送到接收方?
答案就是: 以太网采用了一种很"原始"的方式,它不是把数据包准确送到接收方,而是向本网络内所有计算机发送,让每台计算机自己判断,是否为接收方。这种方式就叫做 “广播”。
比如:1 号计算机向 2 号计算机发送一个数据包,同一个子网络的 3 号、4 号、5 号计算机都会收到这个包。它们读取这个包的"标头"(标头会有接收者的 MAC 地址),找到接收方的 MAC 地址,然后与自身的 MAC 地址相比较,如果两者相同,就接受这个包,做进一步处理,否则就丢弃这个包。
听着有点晕?那我再举个例子:A 班的小明向 B 班的小红表白,但是他只知道她叫小红(MAC 独一无二,不存在相同情况),不知道长相,于是给 B 班的所有同学都写了一封情书,B 班的每位同学都会收到来自小明的信,他们就会读取这封信的接收者名字,和自己的名字比较,如果两者相同,就接受这封信,不同就丢弃。
这时候你又要问了,在同一个子网络可以通过 “广播” 的形式去获得对方的 MAC 地址,可是如果两台电脑不在同一个子网络,就无法知道对方的 MAC 地址,该咋办呢?
这时候就必须通过网关转发。
不懂?那我举个例子,三年级的小红要写一封信给四年级的小张,可是不是同一个年级咋办,这时候小红发现,她的室友小 A 和小张的室友小 B 是邻居,于是她对小 A 说 :“ 喂,我把这信给你,你交给你邻居小 B,让他帮忙交给小张 ” 。最终,信交到了小张的手里。这里小 A 和小 B 就充当了网关的职责。
扯那么多,我们来个实例讲解一下,到底按下的那一瞬间发生了什么!
我们知道,发送数据包和请求,必须要知道对方的 IP 地址,可是我们现在只知道域名,不知道对方的 IP 地址咋办,这时候 DNS 就发挥作用了。
-
假设主机最开始没有 IP 地址以及其它信息,那么就需要先使用 动态主机配置协议 DHCP 来获取
-
主机生成一个 DHCP 请求报文,并将这个报文放入具有目的端口 67 和源端口 68 的 UDP 报文段中。
-
该报文段则被放入在一个具有广播 IP 目的地址(255.255.255.255) 和源 IP 地址(0.0.0.0)的 IP 数据报中
-
该数据报则被放置在 MAC 帧中,该帧具有目的地址 FF:FF:FF:FF:FF:FF,将广播到与交换机连接的所有设备。
-
连接在交换机的 DHCP 服务器收到广播帧之后,不断地向上分解得到 IP 数据报、UDP 报文段、DHCP 请求报文,之后生成 DHCP ACK 报文,该报文包含以下信息:IP 地址、DNS 服务器的 IP 地址、默认网关路由器的 IP 地址和子网掩码。该报文被放入 UDP 报文段中,UDP 报文段有被放入 IP 数据报中,最后放入 MAC 帧中
-
该帧的目的地址是请求主机的 MAC 地址,因为交换机具有自学习能力,之前主机发送了广播帧之后就记录了 MAC 地址到其转发接口的交换表项,因此现在交换机就可以直接知道应该向哪个接口发送该帧。
-
主机收到该帧后,不断分解得到 DHCP 报文。之后就配置它的 IP 地址、子网掩码和 DNS 服务器的 IP 地址,并在其 IP 转发表中安装默认网关。
-
主机通过浏览器生成一个 TCP 套接字,套接字向 HTTP 服务器发送 HTTP 请求。为了生成该套接字,主机需要知道网站的域名对应的 IP 地址。比如我们在浏览器中输入 :
www.baidu.com
之后,会给 DNS 服务器发送一个 DNS 数据包,告诉 DNS : “喂,我要访问www.baidu.com
,你把他的 IP 地址给我” -
主机生成一个 DNS 查询报文,该报文具有 53 号端口,因为 DNS 服务器的端口号是 53。
-
该 DNS 查询报文被放入目的地址为 DNS 服务器 IP 地址的 IP 数据报中。
-
该 IP 数据报被放入一个以太网帧中,该帧将发送到网关路由器。
-
DHCP 过程只知道网关路由器的 IP 地址,为了获取网关路由器的 MAC 地址,需要使用 ARP 协议。
-
主机生成一个包含目的地址为网关路由器 IP 地址的 ARP 查询报文,将该 ARP 查询报文放入一个具有广播目的地址(FF:FF:FF:FF:FF:FF)的以太网帧中,并向交换机发送该以太网帧,交换机将该帧转发给所有的连接设备,包括网关路由器。
-
网关路由器接收到该帧后,不断向上分解得到 ARP 报文,发现其中的 IP 地址与其接口的 IP 地址匹配,因此就发送一个 ARP 回答报文,包含了它的 MAC 地址,发回给主机。
DNS 域名解析过程,如何查找呢?第一种: 采用递归查询,如果主机查询的本地域名服务器不知道被查询域名的 IP 地址,那么本机域名服务器就以 DNS 客户的身份,向其他根域名服务器继续发出从查询请求报文(替主机查询,而不是让主机自己查询),第二种: 采用迭代查询,当根域名服务器收到本地域名服务器发出的迭代查询请求报文后,要么给出查询结果,要么就告诉本地服务器接下来应当向哪个域名服务器查询(让主机自己去查,而不是帮主机查)
-
知道了网关路由器的 MAC 地址之后,就可以继续 DNS 的解析过程了。
-
网关路由器接收到包含 DNS 查询报文的以太网帧后,抽取出 IP 数据报,并根据转发表决定该 IP 数据报应该转发的路由器。
-
因为路由器具有内部网关协议(RIP、OSPF)和外部网关协议(BGP)这两种路由选择协议,因此路由表中已经配置了网关路由器到达 DNS 服务器的路由表项。
-
到达 DNS 服务器之后,DNS 服务器抽取出 DNS 查询报文,并在 DNS 数据库中查找待解析的域名。
-
找到 DNS 记录之后,发送 DNS 回答报文,将该回答报文放入 UDP 报文段中,然后放入 IP 数据报中,通过路由器反向转发回网关路由器,并经过以太网交换机到达主机。
如何判断是否同一网络,通过将 IP 地址和子网掩码进行逐位的“与”运算。也就是做一个二进制的 AND 运算(两个数位都为 1,结果为 1,否则为 0)
-
有了 HTTP 服务器的 IP 地址之后,主机就能够生成 TCP 套接字,该套接字将用于向 Web 服务器发送 HTTP GET 报文。
-
在生成 TCP 套接字之前,必须先与 HTTP 服务器进行三次握手来建立连接。生成一个具有目的端口 80 的 TCP SYN 报文段,并向 HTTP 服务器发送该报文段。
-
HTTP 服务器收到该报文段之后,生成 TCP
SYN
、ACK
报文段,发回给主机。 -
连接建立之后,浏览器生成 HTTP GET 报文,并交付给 HTTP 服务器。通过 TCP 协议,将 HTTP 请求的内容获取。也就是 TCP 数据包 + 嵌入 HTTP 的数据包。TCP 数据包再嵌入到 IP 数据包。IP 数据包需要设置双方的 IP 地址,IP 数据包嵌入以太网数据包。以太网数据包需要设置双方的 MAC 地址(通过 ARP 协议得到),通过物理层二进制数据传输,到了服务器接收方
-
HTTP 服务器接收之后,不断分解,然后从 TCP 套接字读取 HTTP GET 报文,生成一个 HTTP 响应报文,将 Web 页面内容放入报文主体中,发回给主机。
-
浏览器收到 HTTP 响应报文后,抽取出 Web 页面内容,之后进行渲染,显示 Web 页面。
-
浏览器渲染引擎获取到请求文档的内容,将 HTML 解析成 DOM Tree,将 CSS 解析成 CSS Rule Tree,然后构建 Render Tree 有了 Render Tree 之后,接着布局 Render Tree,浏览器已知道网页有哪些节点,各节点的 CSS 定义以及它们的从属关系,去计算每个节点在屏幕中的位置。,然后绘制 render tree。
-
在构建 CSSOM 树时,会阻塞渲染,直至 CSSOM 树构建完成。并且构建 CSSOM 树是一个十分消耗性能的过程,所以应该尽量保证层级扁平,减少过度层叠,越是具体的 CSS 选择器,执行速度越慢。
-
当 HTML 解析到 script 标签时,会暂停构建 DOM,完成后才会从暂停的地方重新开始。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件。并且 CSS 也会影响 JS 的执行,只有当解析完样式表才会执行 JS,所以也可以认为这种情况下,CSS 也会暂停构建 DOM。