URL输入到页面展示的全链路解析

一、域名解析

本地DNS

当一个URL输入到浏览器地址栏中,浏览器会先去本地DNS中查看是否有关于这个域名(URL)对应的IP映射,如果有,则直接获取该IP进行访问。

DNS分为本地DNS、本地DNS服务器、根DNS服务器、顶级DNS服务器、权威DNS服务器,本地DNS是浏览网页第一个经过的点,因为它就是我们的电脑本机,其数据都存在电脑的内存和硬盘中。

本地DNS服务器

如果本地DNS中没有找到该域名对应的IP,那么浏览器会来本地DNS服务器中继续查找。

本地服务器正常都会放在公司的机房中,部分小公司会把DNS服务器嵌入到别的服务器中,以此来节省成本。

根DNS服务器

如果本地DNS服务器中,也没有找到IP,那么浏览器会来请求根DNS服务器,该服务器需要根据域名中的根域名来查找对应的顶级DNS服务器。

根域名是只访问域名中的根部,比如一个百度网址"www.baidu.com" ,其中".com"就是根域名。

根DNS服务器中并不会存储域名的IP映射,它的作用是为浏览器提供准确的顶级DNS服务器。

顶级DNS服务器

根据根DNS服务器的指引,浏览器会准确的找到根域名所对应的顶级DNS服务器。该服务器会根据二级域名来查找对应的权威DNS服务器。

二级域名是域名的中间部分,比如还是一个百度地址"www.baidu.com" ,其中"baidu.com"就是二级域名

权威DNS服务器

最终浏览器在前面层层DNS服务器的帮助下,找到了该域名对应的权威DNS服务器,在该服务器中,可以拿到访问域名对应的IP。此时虽然拿到了,但并不能直接返回给浏览器,而是要先返回给本地DNS服务器,本地DNS服务器拿到IP后,会将这个域名和IP缓存下来,然后再给到浏览器,浏览器拿到IP后就可以对该IP进行访问了。

总体流程

浏览器 → 本地缓存 → 本地DNS服务器 →(递归查询)
          ↓ 若未命中
本地DNS服务器 → 根DNS → TLD DNS → 权威DNS → 获取IP
          ↑________缓存结果_________↓
浏览器 ← IP ← 本地DNS服务器

二、建立连接

这个的建立连接是指TCP的三次握手,具体细节如下:

  1. 第一次握手: 浏览器向服务器发起连接请求包,包内容是SYN报文(SYN=1)和客户端的初始序列号(seq=x)。
  2. 第二次握手: 服务器接收到浏览器发来的请求包后,会向浏览器发送一个请求确认包,包内容SYN-ACK确认报文(SYN=1,ACK=1)、ack确认号(x+1)、服务器初始序列号(seq=y)。
  3. 第三次握手: 浏览器收到后,会再次向服务器端发一个ACK确认包,包内容包含ACK确认报文(ACK=1)、序列号(seq=x+1)、确认号(ack=y+1),服务器收到ACK本文后就代表连接成功,客户端和服务器端此时就能正常通讯了。

总体流程

客户端 → 服务器:SYN=1, seq=x  
客户端状态:SYN-SENT  

服务器 → 客户端:SYN=1, ACK=1, seq=y, ack=x+1  
服务器状态:SYN-RECEIVED  

客户端 → 服务器:ACK=1, seq=x+1, ack=y+1  
客户端状态:ESTABLISHED  
服务器状态:ESTABLISHED(收到ACK后)

三、发送请求

浏览器会根据网页所需要的资源需求(图片、JavaScript脚本、css文件、接口等),构建HTTP请求报文并发送给服务器。

四、处理请求

服务器会根据请求报文的内容,来准备客户端所需要的资源,如果是接口数据,就去数据库中查找并整理好,如果是获取文件,就去服务器读取该文件。

五、响应请求

服务器处理完请求后,会构建HTTP响应报文(状态码、响应头、响应体等),最终将报文响应到客户端。

六、渲染页面

浏览器收到服务器的响应后,开始渲染页面

  1. 渲染HTML:浏览器接收并解析HTML文档,构建HTML DOM树。
  2. 渲染CSS:浏览器解析CSS样式表,构建CSSOM树。
  3. 合成渲染树:将HTML DOM树和CSSOM树合并成渲染树,渲染树只包含可见的元素和样式信息。
  4. 绘制和布局:根据渲染树,将HTML和CSS渲染到页面上。
  5. 执行JavaScript:如果页面中有JavaScript代码,浏览器会按顺序执行JavaScript代码。

七、关闭连接

至此,从输入URL到页面展示的整体任务完成了,客户端或服务器端开始申请关闭连接,这个过程其实就是四次挥手,具体步骤如下(这里的例子主动方是客户端,被动方是服务器端):

  1. 第一次挥手: 客户端向服务器端发送FIN包(FIN=1)和序列号(seq=u),请求关闭连接。
  2. 第二次挥手: 服务器端收到关闭请求后,给客户端发送ACK包(ACK=1)和确认号(ack=u+1)。
  3. 第三次挥手: 服务器端再次向客户端发送关闭请求,携带FIN包(FIN=1)和序列号(seq=k)。
  4. 第四次挥手: 客户端收到服务器端发送的确认包和关闭请求,会回应服务器端一个ACK包(ACK=1)和确认号(ack=k+1)。

总体流程

主动方(客户端)                             被动方(服务器)
---------- 第一次挥手:FIN=1, seq=u ----------→  
(状态:FIN-WAIT-1)                          (状态:ESTABLISHED)

←--------- 第二次挥手:ACK=1, ack=u+1 ----------  
(状态:FIN-WAIT-2)                          (状态:CLOSE-WAIT)

←--------- 第三次挥手:FIN=1, seq=v ----------  
(状态:TIME-WAIT)                           (状态:LAST-ACK)

---------- 第四次挥手:ACK=1, ack=v+1 ----------→  
(等待2MSL后关闭)                            (状态:CLOSED)