浏览器的主要功能简单的概括起来就是:将用户输入的URL转变成可视化的内容图像。那么,作为一个合格的前端,你真地知道从URL到页面渲染完毕过程中都发生了什么吗?不知道?那真不配叫前端!
01前言
当我们打开浏览器从输入网址到网页呈现这个过程,背后到底发生了什么呢?作为一个前端工程师,这是必须要知道的!!!这个过程的总体流程如下图,总的可以分为如下几个步骤:1.DNS 解析:将域名解析成 IP 地址;2.TCP 连接:TCP 三次握手;3.发送 HTTP 请求;4.服务器处理请求并返回 HTTP 报文;5.浏览器解析渲染页面;6.断开连接:TCP 四次挥手。下面我们详细的介绍接几个过程。

02URL是什么
URL是什么?MDN上是这样说的,URL代表着是统一资源定位符(Uniform Resource Locator)。URL无非就是一个给定的独特资源在Web上的地址。理论上说,每个有效的URL都指向一个唯一的资源。这个资源可以是一个HTML 页面,一个CSS文档,一幅图像,等等。
一个URL由不同的部分组成,其中一些是必须的,而另一些是可选的。URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。主要组成如下:
1、协议(protocol):它表明了浏览器必须使用何种协议。常见的协议格式有:HTTP://、HTTPS://、file://、FTP://、mailto:、MMS://、thunder://、Flashget://等等,最常用的是HTTP协议的安全版,即HTTPS。
2、主机名(hostname):比如www.baidu.com是域名,当然也可以是IP地址,两者是等价的。域名的使用只是为了帮助用户更容易地记住这个地址。对于域名www.baidu.com来说,是由两部分构成的,真正在互联网上能唯一标识的顶级域名部分是baidu.com,而www是该顶级域名的一个子域名,比如baidu.com这个顶级域名下除了有www.baidu.com外,还有image.baidu.com或者 pan.baidu.com等。
3、端口号(port):整数,可选,省略时使用方案的默认端口,各种传输协议都有默认的端口号,如http的默认端口为80,https的默认端口为443。如果输入时省略,则使用默认端口号。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项。
4、路径(path)
由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
5、parameters(参数)
这是用于指定特殊参数的可选项,有服务器端程序自行解释。
6、query(查询)
可选,用于给动态网页(如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技术制作的网页)传递参数,可有多个参数,用“&”符号隔开,每个参数的名和值用“=”符号隔开。
7、fragment(信息片断)
也可叫做锚点,字符串,用于指定网络资源中的片段。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释。
03DNS域名解析
1.DNS是什么和IP与域名的关系
在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过 IP 地址。域名是为了方便记忆而专门建立的一套地址转换系统,要访问一台的服务器的互联网,最终还必须通过IP地址来实现,域名解析就是将域名重新转换为IP地址的过程。
一个域名对应一个IP地址,一个IP地址可以对应多个域名;所以多个域名可以同时被解析到一个IP地址。域名解析需要由专门的域名解析服务器(DNS)来完成。
DNS 协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器,我们的域名解析简单来说就是在 DNS 上记录一条信息记录。
2.域名服务器概念
DNS 的核心系统是一个三层的树状、分布式服务,基本对应域名的结构:
根域名服务器(Root DNS Server):管理顶级域名服务器,返回“com”、net”、“cn”等顶级域名服务器的 IP 地址。
顶级域名服务器(Top-level DNS Server):管理各自域名下的权威域名服务器,比如 com 顶级域名服务器可以返回 apple.com 域名服务器的 IP 地址。
权威域名服务器(Authoritative DNS Server):管理自己域名下主机的 IP 地址,比如 apple.com 权威域名服务器可以返回 www.apple.com 的 IP 地址。

3.DNS的解析过程

(1) 在浏览器中输入www.baidu.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
(2) 如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。
(3) 如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/IP参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。
(4) 如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。
(5) 如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(baidu.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找baidu.com域服务器,重复上面的动作,进行查询,直至找到www.baidu.com主机。
(6) 如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用还是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。
至此,你已经获取到缓存服务器的IP地址,并且准备向这个IP地址发送请求了。
04建立TCP连接
拿到了IP地址后,就可以发起HTTP请求了。HTTP请求的本质就是TCP/IP的请求构建。建立连接时需要3次握手 进行验证,断开链接也同样需要4次挥手进行验证,保证传输的可靠性。
1.三次握手
很多人都看过三次握手四次挥手的流程图,但是总是不明白、记不住。最主要的原因还是我们对其含义不理解。可通过下方图文结合方式理解三次握手。
| 消息类型 | 描述 |
| SYN(Synchronize Sequence Numbers,同步序列编号) | 这个消息是用来初始化和建立链接。 |
|
ACK(Acknowledge character,确认字符) | 帮助对方确认收到的 SYN 消息,在连接建立时用来同步序号。当SYN=1而ACK=0 时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使 SYN=1和ACK=1.因此,SYN 置1就表示这是一个连接请求或连接接受报文。 |
|
ack(Acknowledge Number,确认编号) | 接收到的上一次远端主机传来的 seq 然后+1,再发送给远端主机。提示远端主机已经成功接收上一次所有数据。 |
| FIN(Finish,完成) | 用来释放一个连接。当 FIN=1时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。 |
| Seg(Sequence Number列) | 标识了TCP发送端到TCP 接收端的数据流的一个字节 |
(1) 流程图如下:

(2) 三次握手原理:
第一次握手:客户端发送一个带有 SYN(synchronize同步)标志的数据包给服务端。
第二次握手:服务端接收成功后,回传一个带有 SYN/ACK 标志的数据包传递确认信息,表示我收到了。
第三次握手:客户端再回传一个带有 ACK 标志的数据包,表示我知道了,握手结束。
(3) 详细过程:
刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。
-
第一次握手:客户端 发送 SYN=1(初始化建立连接),seq=x 给服务端,消息发完后此时 客户端处于SYN_SENT 状态,等待服务器的确认。
-
第二次握手:服务端收到客户端发送的想要建立连接的信息,会发送ACK=1 表明确认收到消息,并以自己的 SYN=1 报文作为应答,表示可以建立连接,并且也是指定了自己的初始化序列号 seq=y,同时会把客户端的 seq + 1 作为ack 的值(ack=x+1),表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。
-
第三次握手:客户端收到服务端可以建立链接的信息,于是发送 ACK=1 表明确认收到消息, 并且指定序列号seq=x+1(初始为seq=x,第二个报文段所以要+1),同时会把服务端的 seq + 1 作为ack(ack=y+1) 的值,表示自己已经收到了客户端的 SYN,消息发送后,此时 客户端处于 ESTABLISHED(已确认) 状态,服务端接收到此消息后,也变为 ESTABLISHED(已确认) 状态。
(4) 为什么TCP建立一定要三次呢?
-
双方要明确对方接收能力都是正常的,(客户端发之后,服务端可以确定客户端发送能力正常,服务端发送给客户端,客户端可以确定服务端的接收和发送能力正常,最后客户端发送确认,来确定客户端的接收能力。
-
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。假如客户端第一次发送了建立连接的消息(第一次握手),由于网络卡顿了或其他原因,没有及时传达到服务端,过了一会儿时间,客户端迟迟未收到服务端的确认消息,便取消了这次信息传输,但是一段时间后,服务端终于接收到了此条消息,于是向客户端发送可建立连接的消息(第二次握手),如果只有两次握手,那么此时双方的连接就建立了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一直等待客户端发送数据,浪费资源。
05客户端发送HTTP请求
TCP 三次握手结束后,开始发送 HTTP 请求报文。
1.HTTP请求报文
HTTP请求报文主要由三个部分组成:请求行、请求头和请求体。具体如下:
请求行:包含请求方法、URI(请求的资源路径)和HTTP协议版本。
请求头(Header): 包含了客户端向服务器发送的附加信息,例如浏览器类型、字符编码、认证信息等。请求头以键值对的形式存在,多个键值对之间以换行符分隔。
请求体(Body): 存放请求参数,即浏览器向服务器传输数据的实体部分。常用于POST方法提交请求时,发送表单数据、JSON数据等类型的数据。

2.响应码





3.响应

4.HTTP协议各版本的区别
HTTP协议的版本历经多次更新迭代,主要包括 HTTP/1.0、HTTP/1.1和HTTP/2等版本,它们之间的主要区别如下:
(1) HTTP/1.0
-
浏览器与服务器只保持短连接,浏览器的每次请求都需要与服务器建立一个TCP连接,都要经过三次握手,四次挥手。而且是串行请求。
-
由于浏览器必须等待响应完成才能发起下一个请求,造成 “队头阻塞”。
如果某请求一直不到达,那么下一个请求就一直不发送。(高延迟–带来页面加载速度的降低)
(2) HTTP/1.1
目前使用最广泛的版本。
-
支持长连接,通过Connection: keep-alive保持HTTP连接不断开,避免重复建立TCP连接。
-
支持 管道化传输,通过长连接实现一个TCP连接中同时处理多个HTTP请求;只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。服务器会按照请求的顺序去返回响应的内容,无法存在并行响应。(http请求返回顺序按照服务器响应速度来排序,这里也会引入promise.then 和 async await 来控制接口请求顺序)。
-
新增了一些请求方法,如put、delete、options,新增了一些请求头和响应头。
-
支持断点续传, 新增 Range 和 Content-Range 头表示请求和响应的部分内容
-
加入缓存处理(响应头新字段Expires、Cache-Control)
-
增加了重要的头 Host 字段;为了支持多虚拟主机的场景,使用同一个IP地址上可以托管多个域名,访问的都是同一个服务器,从而满足HTTP协议发展所需要的更高级的特性。
劣势:
-
队头阻塞
-
无状态通信模型(巨大的HTTP头部),也就是服务器端不保存客户端请求的任何状态信息。这样会造成一些需求频繁交互的应用程序难以实现,需要通过其他机制来保证状态的一致性等。
-
明文传输–不安全
-
不支持服务端推送
(3) HTTP/2.0
-
采用二进制格式而非文本格式。
-
多路复用,在同一个TCP连接上同时传输多条消息;每个请求和响应都被分配了唯一的标识符,称为“流(Stream)”,这样每条信息就可以独立地在网络上传输。
-
使用 HPACK 算法报头压缩,降低开销。
-
服务器推送,支持服务器主动将相关资源预测性地推送给客户端,以减少后续的请求和延迟。(例如 HTML、CSS、JavaScript、图像和视频等文件)。
(4) HTTP3.0
是 HTTP/3 中的底层支撑协议,该协议基于 UDP,又吸取了TCP中的精华,实现了既快又可靠的协议。
-
运输层由TCP改成使用UDP传输。
-
队头堵塞问题的解决更为彻底。
-
切换网络时的连接保持:基于TCP的协议,由于切换网络之后,IP会改变,因而之前的连接不可能继续保持。而基于UDP的QUIC协议,则可以内建与TCP中不同的连接标识方法,从而在网络完成切换之后,恢复之前与服务器的连接。
-
升级新的压缩算法。
06页面渲染

1.解析HTML,构建DOM树
解析HTML,生成DOM树结构,首先会拿到html整体的字符串,进行标记化(token)。因为浏览器是不能识别这些字符串的,需要进行标记化的处理,本质上就是把这段字符串的html进行标签类型的拆分,因为是一长串的字符串需要对字符串进行解析成node节点,所以会进行标记化,方便浏览器根据标记的标签去进行DOM树渲染。

在网络中传输的内容其实都是0和1这些字节数据。当浏览器接收到这些字节数据以后,它会将这些数据转换为字符串,就是我们的代码。
标记化算法的输入结果是HTML标记,使用状态机表示。状态机一共有4个状态:数据状态(Data)、标记打开状态(Tag open)、标记名称状态(Tag name)、关闭标记打开状态(Close tag open state)。
初始状态是 数据状态。
当标记是处于数据状态时:
(1) 遇到字符 < 时,状态更改为 “标记打开状态”:
a. 接收一个 a-z 字符会创建 “起始标记” ,状态更改为 “标记名称状态” ,并保持到接收 > 字符。此期间的字符串会形成一个新的标记名称。接收到 > 标记后,将当前的 新标记 发送给 树构造器 ,状态改回 “数据状态”。
b. 接收下一个输入字符 / 时,会创建 关闭标记打开状态 ,并更改为 “标记名称状态” 。直到接收 > 字符,将当前的 新标 记发送给 树构造器,并改回 “数据状态” 。
(2) 遇到 a-z字符时,会将每个字符创建成字符标记,并发送给树构造器。
将整个字符串进行了标记化之后,就能够在此基础上构建出对应的 DOM 树出来。

解析过程中遇到 CSS 解析 CSS,遇到 JS 执行 JS。为了提高解析效率,浏览器在开始解析前,会启动一个预解析的线程,率先下载 HTML 中的外部 CSS 文件和 外部的 JS 文件。如果主线程解析到link位置,此时外部的 CSS 文件还没有下载解析好,主线程不会等待,继续解析后续的 HTML。这是因为下载和解析 CSS 的工作是在预解析线程中进行的。这就是 CSS 不会阻塞 HTML 解析的根本原因。如果主线程解析到script位置,会停止解析 HTML,转而等待 JS 文件下载好,并将全局代码解析执行完成后,才能继续解析 HTML。这是因为 JS 代码的执行过程可能会修改当前的 DOM 树,所以 DOM 树的生成必须暂停。这就是 JS 会阻塞 HTML 解析的根本原因,这就是为什么我们建议把 js文件 放在body的最后。
2.解析CSS,构建CSSOM树
构建 CSSOM 树的过程与 构建DOM 的过程非常相似,当浏览器接收到一段CSS,浏览器首先要做的是识别出Token,然后构建节点并生成 CSSOM。这一过程中,CSS匹配HTML元素是一个相当复杂和有性能问题的事情,浏览器要递归CSSOM树,确定每一个节点的样式到底是什么。

3.合成渲染树(样式计算)
当我们生成 DOM 树和 CSSOM 树以后,就需要将这两棵树组合为渲染树。在这一过程中,不是简单地将两者合并就行了。渲染树只会包括需要显示的节点和这些节点的样式信息,如果某个节点是display: none的,那么就不会在渲染树中显示。
主线程会遍历得到的 DOM 树,依次为树中的每个节点计算出它最终的样式,称之为 Computed Style。在这一过程中,很多预设值会变成绝对值,比如red会变成rgb(255,0,0);相对单位会变成绝对单位,比如em会变成px这一步完成后,会得到一棵带有样式的 DOM 树。

4.构建图层树
现在,虽然我们已经有了 render tree 和 css tree,但是我们也无法保证能够正确渲染出页面,因为还会有一些复杂的场景,比如3D动画如何呈现出变换效果,当元素含有层叠上下文时(定位,z-index等)如何控制显示和隐藏等等。所以,还需图层树(layer tree)来解决问题。
构建图层树阶段会依次遍历 DOM 树的每一个节点,计算每个节点的几何信息。例如节点的宽高、相对包含块的位置。大部分时候,DOM 树和布局树并非一一对应。


一般情况下,节点的图层会默认属于父亲节点的图层(这些图层也称为合成层)。那什么时候会提升为一个单独的合成层呢?
有两种情况需要分别讨论,一种是显式合成,一种是隐式合成。
(1)显式合成
-
拥有层叠上下文的节点:HTML根元素本身就具有层叠上下文;普通元素设置position不为static并且设置了z-index属性,会产生层叠上下文;元素的 opacity 值不是 1;元素的 transform 值不是 none;元素的 filter 值不是 none;元素的 isolation 值是isolate;will-change指定的属性值为上面任意一个。
-
需要剪裁的地方:比如一个div,你只给他设置 100 * 100 像素的大小,而你在里面放了非常多的文字,那么超出的文字部分就需要被剪裁。当然如果出现了滚动条,那么滚动条会被单独提升为一个图层。
(2)隐式合成
层叠等级低的节点被提升为单独的图层之后,那么所有层叠等级比它高的节点都会成为一个单独的图层,这个隐式合成其实隐藏着巨大的风险,如果在一个大型应用中,当一个z-index比较低的元素被提升为单独图层之后,层叠在它上面的的元素统统都会被提升为单独的图层,可能会增加上千个图层,大大增加内存的压力,甚至直接让页面崩溃,这就是层爆炸的原理。

这时,我们就不得不聊一聊重排(回流)和 重绘了。
5.重排(回流)和重绘
(1) 重排(回流)
重排(回流)的本质就是重新计算 layout 树。
重排(回流):当DOM的变化引发了元素几何属性的变化,比如改变元素的宽高,元素的位置,导致浏览器不得不重新计算元素的几何属性,并重新构建渲染树,这个过程称为“重排”。

常见的引起重排的操作:
-
一个 DOM 元素的几何属性变化,常见的几何属性有width、height、padding、margin、left、top、border 等等, 这个很好理解;
-
使 DOM 节点发生增减或者移动;
-
读写 offset族、scroll族和client族属性的时候,浏览器为了获取这些值,需要进行回流操作;
-
调用 window.getComputedStyle 方法;
-
浏览器的窗口大小发生变化;
-
元素的字体大小发生变化;
-
添加或删除可见的DOM元素;
-
激活CSS伪类;
-
查询某些属性或者调用某些方法。
(2) 重绘
重绘:完成重排后,要将重新构建的渲染树渲染到屏幕上,这个过程就是“重绘”。
重绘的本质就是重新根据分层信息计算了绘制指令。当改动了可见样式后,就需要重新计算,会引发重绘。

由于元素的布局信息也属于可见样式,所以重排一定引起重绘,但重绘不一定引起重排。重排的成本开销要高于重绘,而且一个节点的重排往往会导致子节点以及同级节点的重排,所以优化方案中一般都包括尽量避免重排。
(6) 生成绘制列表
图层树构建完成后,接下来渲染引擎会将图层的绘制拆分成一个个绘制指令,比如先画背景、再描绘边框…然后将这些指令按顺序组合成一个待绘制列表。主线程会为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。完成绘制后,主线程将每个图层的绘制信息提交给合成线程,剩余工作将由合成线程完成。合成线程首先对每个图层进行分块,将其划分为更多的小区域。它会从线程池中拿取多个线程来完成分块工作。

绘制列表准备好了之后,渲染进程的主线程会给合成线程发送commit消息,把绘制列表提交给合成线程。
但是我们的视口大小有限,但是我们的页面非常大,需要滑动很长时间才能滑到底,如果一次性把全部绘制出来是非常浪费性能的。因此,合成线程要做的第一件事情就是将图层按照分块,然后根据可视区上下的的图库转化成位图,这一步也叫栅格化,这样可以提高页面的首屏展示效率。
栅格化完成后,合成线程会生成一个"DrawQuad"的命令,并发送给浏览器进程,浏览器进程里面有一个叫 viz 的组件,用来接收合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。
07断开链接
1.四次挥手
(1) 流程图如下:

(2) 四次挥手原理:
第一次挥手:客户端发送一个FIN,用来关闭客户端到服务器的数据传送,并且指定一个序列号。客户端进入FIN_WAIT_1状态。
第二次挥手:服务器收到FIN后,发送一个ACK给客户端,确认序号为客户端的序列号值 +1 ,表明已经收到客户端的报文了,此时服务器处于 CLOSE_WAIT 状态。
第三次挥手:服务器发送一个FIN,用来关闭服务器到客户端的数据传送,服务器进入LAST_ACK状态。
第四次挥手:客户端收到FIN后,客户端进入TIME_WAIT状态,接着发送一个ACK给服务器,确认序号为收到序号+1 ,服务器收到确认后进入CLOSED状态,完成四次挥手。
(3) 详细过程:
初始时,客户端和服务端都处于ESTABLISHED(已建立连接状态)。
-
有一方想要发起关闭连接请求(假设为客户端),客户端首先发出 FIN=1, 序列号 seq=u 的结束信号消息,此时 客户端变为 FIN_WAIT1 状态。
-
服务端收到消息后,首先回复 ACK=1, ack=u+1, seq=v 表明收到上一条想要结束连接的消息,此时服务端变为 CLOSE_WAIT 状态,接下来服务端会去检查是否可以结束连接(没有需要再传输的请求或数据)。客户端收到上一条消息后,变为 FIN_WAIT2 状态,继续等待服务端可以结束连接的消息传来。
-
服务端确定可以断开连接后,会再向 客户端发送 FIN=1(结束标志), ACK =1,ack = u+1, seq = w 的消息表明可以结束连接的消息,此时服务端变为 LAST_ACK(最后一次发送消息)状态,等待 客户端的 确认。
-
客户端收到FIN消息后,回复 ACK=1,ack=w+1,seq=u+1表明收到上一条可以结束的消息,此时客户端变为 TIME_WAIT状态,并设置时间等待定时器时间 为2MSL,这么做的原因是确保消息被服务器接收到,定时器时间到后,客户端才会变为CLOSED状态(客户端(发起结束信号的一方)主动变为CLOSED状态)。服务端收到上一条消息后,状态变为 CLOSED(客户端(接收结束信号的一方)是被动变为CLOSED)。
(4) 为什么需要四次挥手才能结束连接?
因为一旦建立连接,双方既是发送方,又是接收方,为了保证在最后断开的时候,客户端发送的最后一个ACK报文段能够被服务器接收到。如果接收结束消息的一方收到FIN=1,seq=u 这条想要结束连接的消息后,就直接回复FIN=1(结束标志), ACK =1,ack = u+1, seq = w 消息,确定可以结束连接,最终连接被关闭,双方变为CLOSE状态,那么如果在收到第一条想要结束的消息时,还有将要传输或者正在进行的消息传输就会被被迫终止,所以必须在这之前先回复一条收到消息的报文,在对自身是否可以断开连接进行检查,确保已没有需要传输信息后,再回复FIN来结束连接。
(5) 四次挥手释放连接时,等待2MSL的意义是什么?
MSL(最长报文段寿命):报文在网络上存活的最长时间,超过这个时间报文将会被丢弃。
-
确保客户端(主动结束方发送)的最后一条消息不被丢失。如果最后一条消息被丢失了,服务端没有收到这条消息,因为服务端在发出SYN+ACK这条消息后,会设置一个重传定时器,在规定的时间内没有收到来自客户端的确认,会重传第三条消息,再次设置定时器,假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一旦这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
-
防止“已失效的连接请求报文段”出现在本连接中。客户端(主动结束方发送)在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
08小结
整个过程如下:
-
浏览器接收url并开启一个新进程。(这一部分可以展开浏览器的进程与线程的关系)
-
浏览器解析输入的 URL,提取出其中的协议、域名和路径等信息。(这部分涉及URL组成部分)
-
浏览器向 DNS 服务器发送请求,DNS服务器通过 多层查询 将该 域名 解析为对应的 IP地址 ,然后将请求发送到该IP地址上,与 服务器 建立连接和交换数据。(这部分涉及DNS查询);
-
浏览器与服务器建立 TCP 连接。(这部分涉及TCP三次握手/四次挥手/5层网络协议)
-
浏览器向服务器发送 HTTP 请求,包含请求头和请求体。(4,5,6,7包含http头部、响应码、报文结构、cookie等知识)
-
服务器接收并处理请求,并返回响应数据,包含状态码、响应头和响应体。
-
浏览器接收到响应数据,解析响应头和响应体,并根据状态码判断是否成功。
-
如果响应成功,浏览器接收到http数据包后的解析流程(这部分涉及到html词法分析,解析成DOM树,解析CSS生成CSSOM树(样式树),合并生成render渲染树。然后layout布局,painting渲染,复合图层合成,调用GPU绘制等,再显示在屏幕上。这个过程会发生回流和重绘)。
-
连接结束 -> 断开TCP连接 四次挥手。
4973

被折叠的 条评论
为什么被折叠?



