从输入url到页面完成加载发生了什么(完整版)

本文详细阐述了从在浏览器地址栏输入URL到页面完全加载显示的全过程,包括DNS解析、TCP连接建立、HTTP请求与响应、页面渲染以及TCP连接关闭等关键步骤。

在写这篇文章之前本想着这个知识点涉及知识点太多太杂,找一篇大牛写的看看就算了,但是看了大概七八篇后,内心更纠结了——🙃🙃🙃真的好杂。。。记忆点找不到了,搞的心里乱乱的,大概是纠结症犯了。所以还是动手总结一下,让自己有个可以抓取的记忆点,也让自己对这个知识点有个浅显的认知。本文旨在讲述发生的流程,如想深究的可自行度娘哦~,其中穿插的知识点及概念我会放到小框里或者贴参考链接。

先来个流程总述:

  • DNS解析:将域名解析成IP地址
  • TCP连接:TCP三次握手
  • 发送HTTP请求
  • 服务器处理请求并返回HTTP报文
  • 浏览器解析渲染页面
  • 连接结束:TCP四次挥手
1、DNS解析

在浏览器输入URL后,首先要经过域名解析。浏览器通过向 DNS 服务器发送域名,DNS 服务器查询到与域名相对应的 IP 地址,然后返回给浏览器,浏览器再将 IP 地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。

1.什么是URL
URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。比如 http://www.w3school.com.cn/ht...,
遵守以下的语法规则:
`scheme://host.domain:port/path/filename`
各部分解释如下:
scheme:定义因特网服务的类型。常见的协议有 httphttpsftpfile,其中最常见的类型是 http,而 https 则是进行加密的网络传输。
host:定义域主机(http 的默认主机是 www)
domain:定义因特网域名,比如 w3school.com.cn
port:定义主机上的端口号(http 的默认端口号是 80)
path: 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
filename: 定义文档/资源的名称

2. 什么是DNS
DNS(domain name system,域名系统):因特网上域名和IP地址相互映射的分布式数据库;简单理解就是域名与IP地址的对照表,因为域名(如:www.google.com)对于我们而言,更便于记忆,但是机器却不擅长这种表达方式,因此需要将域名转换为IP地址,以便于机器识别, 这便有了DNS3. 根域名服务器
根服务器是架设互联网的必须设施,管理互联网的主目录,全球共有13套根域名服务器

4. 递归查询
客户端主机向本地域名服务器的查询是递归查询;所谓递归查询:客户端主机查询的域名地址无法在本地域名服务器中找到,因此本地域名服务器就以DNS客户端的身份向其他根域名服务器发起请求,进行查询,而不是让客户端主机去一直查询;
递归查询的结果要么是返回的IP地址,要么是报错,表示无法查询到地址;

5. 迭代查询
本地域名服务器向根服务器、顶级域名服务器和主机域名服务器发起的查询请求就是迭代的过程,如:本地域名服务器向根服务器发起查询请求,根服务器中会告诉本地域名服务器:”我这里没有你要找的内容,你去顶级域名服务器上找吧“,并将顶级域名服务器的地址返回给本地域名服务器,本地域名服务器接收到后,继续向顶级域名服务器发送请求;顶级域名服务器要么返回ip地址,要么告诉本地域名服务器下一步要向哪个权限域名服务器发送请求,直到找到ip地址或找不到ip返回报错信息,然后信息返回给客户端主机;
下图给出了这两种查询的差别

递归过程:主机→本地DNS服务器→其他DNS服务器(如:我要找一个苹果吃,找到了A,问A有没有,A说我帮你去找BB可能有,果真B有,然后B将苹果给了AA再将苹果给我,这就是递归)
迭代过程:本地DNS服务器→根服务器,本地DNS服务器→顶级域名服务器,本地DNS服务器→权限域名服务器;(如:我要找一个苹果,找到了AA说我也没有,B可能有,你去找B吧;我又找BB说我也没有,你去找C吧,我又去找C,终于找到了苹果,这就是迭代的过程)
复制代码
2、TCP连接:TCP三次握手

在客户端发送数据之前会发起 TCP 三次握手用以同步客户端和服务端的序列号和确认号,并交换 TCP 窗口大小信息。

在这里插入图片描述
说明:
    Ack:应答
    Fin:结束; 结束会话
    Seq: 一个数据段的第一个序列号
    SYN: 同步; 表示开始会话请求
复制代码
  • 第一次握手:客户端A将标志位SYN置为1,随机产生一个值为seq=X(X的取值范围为=1234567)的数据包到服务器,客户端A进入SYN_SENT状态,等待服务端B确认(第一次握手,由浏览器发起,告诉服务器我要发送请求了);
  • 第二次握手:服务端B收到数据包后由标志位SYN=1知道客户端A请求建立连接,服务端B将标志位SYN和ACK都置为1,ack=X+1,随机产生一个值seq=Y,并将该数据包发送给客户端A以确认连接请求,服务端B进入SYN_RCVD状态(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)。
  • 第三次握手:客户端A收到确认后,检查ack是否为X+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=Y+1,并将该数据包发送给服务端B,服务端B检查ack是否为Y+1,ACK是否为1,如果正确则连接建立成功,客户端A和服务端B进入ESTABLISHED状态,完成三次握手,随后客户端A与服务端B之间可以开始传输数据了(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)。

为什需要三次握手? 计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。 书中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。 假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。

3、浏览器向web服务器发送HTTP请求

TCP三次握手之后,开始发送HTTP请求报文至服务器(关于HTTP请求报文详解,我单独写了一篇☞传送门

HTTP请求报文格式:请求行+请求头+空行+消息体,请求行包括请求方式(GET/POST/DELETE/PUT)、请求资源路径(URL)、HTTP版本号;

4、服务器处理请求并返回HTTP报文

服务器收到请求后会发出应答,即响应数据。HTTP响应与HTTP请求相似, HTTP响应报文格式:状态行+响应头+空行+消息体,状态行包括HTTP版本号、状态码、状态说明。

5、浏览器解析渲染页面

浏览器拿到响应文本后,解析HTML代码,请求js,css等资源,最后进行页面渲染,呈现给用户。页面渲染一般分为以下几个步骤:

(1)根据HTML文件解析出DOM Tree

(2)根据CSS解析出 CSSOM Tree(CSS规则树)

(3)将 DOM Tree 和 CSSOM Tree合并,构建Render tree(渲染树)

(4)reflow(重排):根据Render tree进行节点信息计算(Layout)

(5)repaint(重绘):根据计算好的信息绘制整个页面(Painting)

6、TCP四次挥手。

当数据传输完毕,需要断开TCP连接,此时发起tcp四次挥手

1、客户端向服务端发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(由浏览器告诉服务器,我请求报文发送完了,你准备关闭吧)

2、服务端向客户端发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。(由服务器告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)

3、服务端向客户端发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(由服务器告诉浏览器,我响应报文发送完了,你准备关闭吧)

4、客户端向服务端发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。(由浏览器告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)

简单说就是:

1、A——>B :A告诉B:“我发完了”;

2、B——>A:B告诉A:“好的,我知道你发完了”

3、B——>A:B告诉A:“我收完了”;

4、A——>B:A告诉B:“好的,我知道你发收完了”

后话

以上基本就是在地址栏从输入 URL 到页面加载显示发生的全过程,当然还有很多的细节没有写进去,不过这些知识对于前端来说已经足够了,有兴趣的小伙伴可以自行深究。最后,小生乃前端小白一枚,写文章的最初衷是为了让自己对该知识点有更深刻的印象和理解,写的东西也很小白,文中如有不对,欢迎指正~ 然后就是希望看完的朋友可以点个喜欢,也可以关注一波~ 我会持续输出!

个人博客链接

GitHub

优快云个人主页

掘金个人主页

简书个人主页

来源:https://juejin.cn/post/6844904122206912526
<think>我们正在讨论从输入URL页面加载完成的详细过程。这是一个经典的浏览器工作原理问题。我将结合引用内容和我掌握的知识进行详细说明。 根据引用[1]和[2],这个过程可以分解为以下几个主要步骤: 1. 浏览器接收URL并开启新进程 2. 解析URL 3. DNS域名解析 4. 建立TCP连接(三次握手) 5. 发送HTTP请求 6. 服务器处理请求并返回HTTP响应 7. 浏览器解析渲染页面 8. 关闭TCP连接(四次挥手) 下面详细说明每个步骤: ### 1. 浏览器接收URL并开启新进程 当用户在浏览器地址栏输入URL并按下回车后,浏览器首先会判断该URL是否合法,然后根据URL协议决定如何处理(例如http、https、ftp等)。浏览器是多进程架构,每个标签页通常运行在独立的渲染进程中(但同源标签页可能会合并进程)[^1]。 - 浏览器进程:负责用户界面、网络请求等。 - 渲染进程(浏览器内核):负责页面渲染和脚本执行,内部是多线程的,包括: - GUI渲染线程:渲染页面布局和绘制。 - JavaScript引擎线程:解析和执行JavaScript代码(如V8引擎)。 - 事件触发线程:管理事件循环。 - 定时器线程:处理setTimeout和setInterval。 - 异步HTTP请求线程:处理XMLHttpRequest等。 注意:GUI渲染线程与JS引擎线程互斥,因此JS执行会阻塞页面渲染[^1]。 ### 2. 解析URL 浏览器解析URL的协议、主机名、端口、路径和查询参数等。例如: ``` http://www.example.com:80/path?query=string#fragment ``` - 协议:http - 主机名:www.example.com - 端口:80(默认端口可省略) - 路径:/path - 查询参数:query=string - 片段标识符:#fragment(用于页面内定位) ### 3. DNS域名解析 浏览器通过DNS将主机名解析为IP地址,过程如下[^2]: 1. **浏览器缓存**:检查自身缓存中是否有对应的DNS记录。 2. **操作系统缓存**:检查操作系统的hosts文件(如`/etc/hosts`)和本地DNS缓存。 3. **本地域名服务器(LDNS)**:向本地配置的DNS服务器(如路由器或ISP提供的DNS)发起查询。 4. **根域名服务器**:若LDNS没有记录,则向根域名服务器查询(返回顶级域名服务器地址)。 5. **顶级域名服务器(TLD)**:查询负责该顶级域(如.com)的服务器(返回权威域名服务器地址)。 6. **权威域名服务器**:查询负责该域名的服务器(如example.com的NS记录),最终获得IP地址。 DNS解析过程通常使用UDP协议,端口53。为了提高效率,DNS结果会被缓存。 > 注:若DNS解析后发现域名和IP不一致(如CDN的IP),浏览器会访问该IP对应的服务器[^1]。 ### 4. 建立TCP连接(三次握手) 浏览器获取到IP地址后,通过TCP协议与服务器建立连接(TCP是面向连接的可靠传输协议): 1. **第一次握手**:客户端发送SYN包(SYN=1, seq=x)到服务器,进入SYN_SENT状态。 2. **第二次握手**:服务器收到SYN包,回应SYN+ACK包(SYN=1, ACK=1, seq=y, ack=x+1),进入SYN_RCVD状态。 3. **第三次握手**:客户端收到SYN+ACK包,发送ACK包(ACK=1, seq=x+1, ack=y+1),双方进入ESTABLISHED状态。 为什么是三次握手?主要是为了防止已失效的连接请求报文突然传送到服务器而产生错误(如因网络延迟导致早先的SYN包迟到)[^1]。 ### 5. 发送HTTP请求 TCP连接建立后,浏览器发送HTTP请求报文到服务器。请求报文包括: - **请求行**:方法(GET/POST等)、URL路径、协议版本(如HTTP/1.1)。 - **请求头**:包含浏览器信息(User-Agent)、接受的数据类型(Accept)、Cookie等。 - **请求体**:对于POST请求,包含提交的数据(如表单数据)。 ### 6. 服务器处理并返回响应 服务器接收到请求后,根据请求路径和参数生成响应内容: - **状态行**:协议版本、状态码(如200 OK)、状态描述。 - **响应头**:服务器信息(Server)、内容类型(Content-Type)、缓存控制(Cache-Control)、设置Cookie等。 - **响应体**:实际返回的数据(HTML文档、图片等)。 常见状态码: - 200:请求成功。 - 301/302:重定向。 - 404:资源未找到。 - 500:服务器内部错误。 ### 7. 浏览器解析渲染页面 浏览器接收到HTML响应后开始解析渲染: 1. **解析HTML构建DOM树**:HTML解析器将HTML转换为DOM树(Document Object Model)。 2. **样式计算(CSSOM)**:解析CSS(包括内联、外部和用户样式)生成CSSOM树(CSS Object Model)。 3. **布局(Layout)**:结合DOM和CSSOM生成渲染树(Render Tree),计算每个节点的几何位置(回流)。 4. **分层(Layer)**:将页面分为多个图层(如对定位元素、透明元素分层)。 5. **绘制(Paint)**:将渲染树转换为屏幕上的像素(重绘)。 6. **栅格化(Raster)**:将图层分割成图块(tiles),并通过GPU加速栅格化。 7. **合成与显示(Composite)**:将栅格化后的图块合成完整页面并显示。 注意: - 遇到`<script>`标签会暂停HTML解析,下载并执行JavaScript(除非标记`async`或`defer`)[^1]。 - CSS不会阻塞DOM解析,但会阻塞渲染(避免FOUC问题)[^1]。 ### 8. 关闭TCP连接(四次挥手) 页面加载完成后,若不需要保持连接(HTTP/1.0默认关闭,HTTP/1.1默认持久连接),则关闭TCP连接: 1. **第一次挥手**:客户端发送FIN包(FIN=1, seq=u)请求断开连接。 2. **第二次挥手**:服务器收到FIN包,发送ACK包(ACK=1, ack=u+1)确认。 3. **第三次挥手**:服务器处理完数据后再发送FIN包(FIN=1, seq=v)。 4. **第四次挥手**:客户端收到FIN包,发送ACK包(ACK=1, ack=v+1)并等待一段时间后关闭连接。 为什么是四次挥手?因为TCP是全双工通信,双方需分别关闭发送通道。 ### 其他注意事项 - **HTTP缓存策略**:浏览器会根据响应头的缓存控制(Cache-Control、ETag、Expires等)决定是否使用本地缓存[^1]。 - **HTTP协议版本**:HTTP/1.1支持持久连接(避免多次握手),HTTP/2支持多路复用和头部压缩,HTTP/3基于QUIC协议(UDP)[^1]。 整个过程涉及网络协议、浏览器渲染引擎、操作系统等多领域的协作。 --- §§相关问题§§ 1. 浏览器渲染过程中如何优化关键渲染路径? 2. DNS解析的详细步骤是什么?如何减少DNS解析时间? 3. HTTP/2相较于HTTP/1.1有哪些性能优化? </think>### 从输入 URL页面加载完成的详细过程 #### 1. **URL 解析与准备** - **URL 结构解析** 浏览器解析 URL 协议(如 `http/https`)、主机名(`www.example.com`)、端口(默认 80/443)、路径(`/index.html`)和查询参数(`?id=123`)。 - **安全检查** 检查是否为合法 URL,阻止恶意协议(如 `javascript:` 或 `file://`)[^1]。 #### 2. **DNS 域名解析** [^2] 浏览器通过 DNS 将域名转换为 IP 地址,过程如下: 1. **浏览器缓存**:检查本地缓存是否有解析记录。 2. **操作系统缓存**:查询系统 hosts 文件。 3. **本地 DNS 服务器**:向 ISP 提供的 DNS 服务器发起请求。 4. **递归查询**:若未命中,本地 DNS 依次查询: - **根域名服务器**(返回顶级域名服务器地址) - **顶级域名服务器**(如 `.com`,返回权威域名服务器地址) - **权威域名服务器**(返回目标域名的 IP 地址)。 5. **解析结果缓存**:将 IP 地址缓存至本地,减少后续查询耗时。 > 注:若 DNS 解析发现域名与 IP 不一致(如 CDN 节点),浏览器仍会访问返回的 IP[^1]。 #### 3. **建立 TCP 连接(三次握手)** 浏览器通过 TCP 协议与目标服务器建立可靠连接: 1. **SYN**:客户端发送 `SYN=1, seq=x` 包。 2. **SYN-ACK**:服务器响应 `SYN=1, ACK=1, seq=y, ack=x+1`。 3. **ACK**:客户端确认 `ACK=1, ack=y+1`。 **为何三次握手?** 防止因网络延迟导致的无效连接请求[^1]。 #### 4. **发送 HTTP 请求** TCP 连接建立后,浏览器发送 HTTP 请求报文: - **请求行**:方法(GET/POST)、路径、协议版本(HTTP/1.1)。 - **请求头**: ```http Host: www.example.com User-Agent: Chrome/... Accept: text/html Cookie: session_id=abc123 ``` - **请求体**:POST 请求的表单数据或 JSON 载荷。 #### 5. **服务器处理与响应** 服务器处理请求并返回 HTTP 响应: - **状态行**:状态码(如 `200 OK`、`404 Not Found`)。 - **响应头**: ```http Content-Type: text/html; charset=utf-8 Cache-Control: max-age=3600 Set-Cookie: new_session=xyz ``` - **响应体**:HTML 文档、CSS、JS 等资源。 #### 6. **浏览器渲染页面** [^1] 浏览器解析响应内容并渲染: 1. **构建 DOM 树** HTML 解析器将 HTML 转换为 DOM 树结构。 2. **构建 CSSOM 树** 解析 CSS 生成 CSS Object Model(CSS 会阻塞渲染)。 3. **合并渲染树(Render Tree)** 结合 DOM 和 CSSOM,排除不可见元素(如 `<head>`)。 4. **布局(Layout)** 计算元素的几何位置(可能触发**回流**)。 5. **绘制(Paint)** 将渲染树转换为屏幕像素(可能触发**重绘**)。 6. **合成(Composite)** 将分层内容(如定位元素)合并后显示到屏幕。 #### 7. **加载子资源** - 解析到 `<img>`, `<script>`, `<link>` 时,发起额外请求获取资源。 - **JS 执行阻塞渲染**:GUI 线程与 JS 引擎线程互斥,需等待 JS 执行完毕(除非标记 `async/defer`)[^1]。 #### 8. **TCP 连接关闭(四次挥手)** 页面加载完成后断开连接: 1. 客户端发送 `FIN` 包请求关闭。 2. 服务器响应 `ACK`。 3. 服务器发送 `FIN` 包。 4. 客户端响应 `ACK` 并等待超时关闭。 ### 关键优化点 1. **DNS 预解析** `<link rel="dns-prefetch" href="//cdn.example.com">` 提前解析域名。 2. **HTTP 缓存** 利用 `Cache-Control` 和 `ETag` 减少重复请求[^1]。 3. **减少重排重绘** 避免频繁操作 DOM 或修改样式。 4. **异步加载资源** 使用 `async/defer` 延迟 JS 执行,避免阻塞渲染。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值