前言
简答:
- 输入网址后首先进行DNS域名解析,获取ip
- 建立TCP链接,请求资源
- 浏览器解析资源,生成树css树+cssOM合成render树
- 渲染生成dom
升级思考:
- DNS域名解析全过程可否阐述一下?
- 请详细阐述一下建立TCP链接全过程?
- 拿到网络资源后浏览器具体做了哪些事情?
DNS域名解析过程
DNS概述
DNS全称(Domain Name System),域名解析系统,在互联网中主机都是由ip地址来标识的,但是ip就跟人的身份证一样难记,然后就有了域名这个东西,就类似于人的姓名,然后就有了ip的域名对应关系的管理系统。
域名解析流程
举例:www.baidu.com/ 以下流程找到主机对应ip直接中断后续查询
- 查看浏览器缓存是否有对应ip记录
- 查看本地host文件有没有配置
- 查找本地最近的DNS域名服务器(ISP-互联网服务商,中国电信,中国网通)查找,该服务器首先查找缓存,有直接返回ip,没有通过根域名服务器查找
- 咨询根域名服务器,.com对应的服务器地址,得到ip
- 咨询顶级域名服务器,baidu.com对应的服务器地址,得到ip
- 咨询权威域名服务器,www.baidu.com 对应的ip地址,得到ip
- ip地址通过本地dns服务返回给浏览器
建立TCP连接全过程
TCP建立连接概述
TCP连接是发生在网络分层(应用层,传输层,网络层,数据链路层,物理层)中的传输层,是基于连接进行通信的,所有要有三次握手,四次挥手的过程,而UDP则不需要,它不是基于连接的,TCP建立连接主要分为三步:
- 三次握手
- 互信通信
- 四次挥手
三次握手
- 客户端发送一堆连接请求数据(SYN包),此时需要传递的有SYN=1(开启同步),seq=xxx(一个随机序列号)给服务端,告诉服务端,我要建立连接了
- 服务端回复客户端SYN+ACK包,此时传递的有SYN = 1,ACK = 1,seq = y(服务器生成自己的序号),ack = x + 1(客户端序号+ 1)告诉客户端,允许连接
- 客户端发送ACK包给服务端,此时传递的有ACK = 1,seq = x + 1,ack = y + 1,建立连接成功
是否可以改为两次握手?
不能,因为客户端发送连接请求报文过程中可能由于网络原因导致滞留网络,超时会再次请求连接,网络通畅后之前的连接也会连接成功,并长时间不关闭,造成浪费。
如何处理在传输过程中的丢包问题,乱序问题?
TCP连接为每一个连接建立了一个发送缓冲区,此缓冲区里的内容都依次排列有自己的序列号,每次发送过去时带上序列号,以一定的规则传送给服务端,服务端根据序列号进行数据组装,如果丢包,会告诉客户端,某段序列号的包数据丢失重新发送。
- 发送报文 = 序列表 + 长度 + 数据内容
- 回复确认ACK = 序列号 + 长度 = 下一次起始序列号
四次挥手
此过程客户端和服务端都可主动发起关闭连接的请求,假设客户端主动发起
- 客户端发送(FIN)包,此时需要传递的有,FIN = 1,ACK = 1,seq = m,ack = v告诉服务端我想断开连接了,你准备好了吗?
- 服务端发送(ACK)包,此时需要传递的有,ACK = 1,seq = v,ack = m + 1告诉客户端,稍等下还没结束
- 服务端发送(FIN + ACK)包,此时需要传递的有,FIN = 1,ACK = 1,seq = v,ack = m + 1,告诉客户端,已经准备好了
- 客户端发送(ACK)包,此时需要传递的有,ACK = 1,seq = m + 1,ack = v + 1,告诉服务端,我断开连接了
为什么会有超时等待关闭时间?
因为客户端如果立即关闭,服务端可能就收不到ACK包,永远处于等待关闭状态。
可以只有三次挥手吗?
不可以,因为如果只有三次挥手可能导致传输数据丢失。
浏览器拿到网络资源后,浏览器做了哪些事情呢?
浏览器概述
浏览器是多进程多线程的应用程序,浏览器启动后默认会启动三个进程:浏览器进程,网络进程,渲染进程,当然可以启动更多,浏览器默认是一个tab页一个进程的。
进程?
进程是CUP资源分配的最小单位,就类似于一个工厂的多个车间,当然启动一个进程会单独的开辟一片内存空间,且相互独立,一般不直接通信
线程
线程是CPU资源调度的最小单位,就类似与一个工厂中某个车间的多条流水线,公用同一片内存空间,可以相互通信
浏览器的渲染机制
- 解析html生成DOM树,从上往下执行
- 解析css,生成cssom树,解析html和css可以同时进行
- 当然如果在解析过程中遇到script标签引入js,此时会阻塞解析过程,会先下载js文件,下载完成后会立即执行js文件
- js文件可以使用async或defer进行异步的加载,区别在于async下载完之后立即执行,不保证先后顺序,defer会在页面解析完成之后进行(先于DOMContentLoaded 事件执行之前执行)
- 将解析后css树+cssom树合成render树
- (layout)在render树的基础上,计算布局,计算每个节点的几何结构
- (layer)浏览器会进行分层处理,如果一个层改变,仅仅对该层进行后续处理,提高效率
- (paint)主线程为每一层单独产生绘制指令,用于描述每一层该如何绘制
- (composite)主线程将每一层的绘制信息交给合成线程,合成后分块,分块后交给GPU 10.(Raster)光栅化(GPU完成),将每个块变成位图(优先处理靠近视口的块)
- 画图(合成线程中完成)
layer分层
一些特殊的属性会形成新的合成层(图层),新的图层可以用GPU渲染加速
- transform(不会影响布局,也不会影响绘制指令生成,只在画图阶段完成,由于画图是在合成线程中完成,不会影响渲染主线程)
- video,canvas,iframe
- animation 或 transition 设置了opacity、transform;
浏览器主线程是如何工作的呢?(Event loop)
- 主线程同时只能去处理一件事情,需要放在任务队列中等待处理,此时等待处理的任务队列也是有优先级概念
- 任务没有优先级,但是消息队列有优先级
- 消息队列可以有多个,同一类型的任务必须在一个队列,不同类型的任务可以处于不同的队列
- 计时器任务:setTimeout,setInterval
- 网络任务::Xhr,Fetch请求回调
- 交互任务:addEventListener等多种任务类型
- 微【微任务】队列(最高),交互队列(高),延时【定时器】队列(中)