由于上次面试,没有准备这题,就很尴尬的浅层次回答,使得面试更加的焦灼起来。
所以我先借这次的机会,认真的看看和理解这道题。
我看了很多的文章,得出一些心得,URL的输入到浏览器解析大概经历了以下几个过程。
URL解析
DNS查询
TCP/IP连接
HTTP请求
响应请求
页面渲染
TCP断开链接
URL解析
首先我们要了解的预备知识
URL是统一资源定位符,用来表示是某个资源的地址
URL的组成
URL 主要由 协议
、域名
、端口
、路径
、查询参数
、锚点
6部分组成!
http://www.example.com:80/path/index.html?key1=value1&key2=value2#SomewhereInTheDocument
http
是协议。它表明了浏览器必须使用何种协议,常用的协议是http,https。www.example.com
是域名,也可以是IP地址。:80
是端口。 同一个域名下面可能同时包含多个网站,它们之间通过端口(port)区分。http协议默认端口是:80端口,如果不写默认就是:80端口,https为443。/path/index.html
是网络服务器上资源的路径网络资源在服务器中的指定路径,例如上边的例子就是指向网站的/path
子目录下面的网页文件index.html
。?key1=value1&key2=value2
是提供给网络服务器的额外信息。如果要向服务器传入参数,在这部分输入。#SomewhereInTheDocument
是资源本身的另一部分的锚点.浏览器加载页面以后,会自动滚动到锚点所在的位置。锚点名称通过网页元素的id
属性命名。
如何解析
在地址栏输入URL后,浏览器会对UR解析,抽取出域名字段,例如我们输入www.baidu.com。就会解析出www.baidu.com
这个域名。
然后接下来就是DNS解析
DNS解析
可以这样理解域名解析。将域名解析为IP地址,浏览器会发送一个UDP的包给DNS域名解析服务器。
DNS查询的工作方式:
客户端和浏览器,本地DNS之间的查询方式是递归查询;
本地DNS服务器与根域及其子域之间的查询方式是迭代查询;
我们先看一张图,看下整个解析过程:
递归查询
我们的浏览器、操作系统、路由器都会缓存一些URL对应的IP地址,统称为DNS高速缓存。这是为了加快DNS解析速度,使得不必每次都到根域名服务器中去查询。
递归查询的步骤有
第一步:浏览器缓存查询,现在浏览的缓存中查找是否有对应的域名的IP,如果有,该解析过程将会结束,如果没有进入下一步。
第二步:系统缓存查询,操作系统会检查自己本地的hosts文件。如果有,就先调用这个IP地址,完成域名解析。如果没有的话,就会进入第三步
第三步:路由器缓存查询,路由器有自己的DNS缓存,如果在路由器的缓存中没有找到对应的IP,就会进入下一步。
第四步:DNS服务器查询,这里就是迭代查询
迭代查询
整个递归查找过程如下:
例如我们访问:www.baidu.com
,在递归查询中没有查找到
本地域名服务器查询根域名服务器,该过程并不会返回映射关系,只会告诉你去下级服务器(顶级域名服务器)查询
本地域名服务器查询顶级域名服务器(即com服务器),同样不会返回映射关系,只会引导你去二级域名服务器查询
本地域名服务器查询二级域名服务器(即baidu.com服务器),此时已经是最后一级了,如果有则返回映射关系。
拿到IP后传给本地的DNS,然后返回给电脑,同时也会进行缓存,以便下次快速进入,最后来和目标服务器建立连接。
注意:迭代是不会自己去查询ip,而是查找相关的服务器IP地址返回给客户端,客户端会不断的向这些服务器进行查询,直到查询到了位置。
经过一番的查询就会得到IP开始建立链接:
TCP/IP连接
预备知识
SYN 同步位 SYN=1 表示进行一个链接请求
ACK 确认位 ACK=1 确认有效 ACK=0 确认无效
ack 确认号 对方发送的 序号+1
seq 序号 随机的
FIN 终止 FIN= 1数据已经发送完毕,并且要求释放。
简单小对话,基础了解三次握手
C:我要给你发信息了
S:好的,我准备好了,你发吧
C:好的,收到
在DNS解析后得到IP,这时就该建立链接,建立链接就会经历三次握手
- 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
TCP 三次握手结束后,开始发送 HTTP 请求报文。
HTTP请求
发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口 请求报文由请求行,请求头,请求体组成。
请求行
包含请求方法、URL、协议版本
- 请求方法包含 8 种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
- URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成
- 协议版本即 http 版本号
请求头
请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中比如:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。
请求体
可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。上面图片,承载着 name、password、realName 三个请求参数。
响应请求
每台服务器上都会安装处理请求的应用——web server。常见的 web server 产品有 apache、nginx、IIS 或 Lighttpd 等。web server 担任管控的角色,对于不同用户发送的请求,会结合配置文件,把不同请求委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端 JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应。
HTTP的响应报文也由三部分组成(响应行+响应头+响应体)
从服务器请求的HTML,CSS,JS文件就放在响应体里面。
状态码,它以“清晰明确”的语言告诉客户端本次请求的处理结果。
1xx:指示信息–表示请求已接收,继续处理。
2xx:成功–表示请求已被成功接收、理解、接受。
3xx:重定向–要完成请求必须进行更进一步的操作。
4xx:客户端错误–请求有语法错误或请求无法实现。
5xx:服务器端错误–服务器未能实现合法的请求。
页面渲染
在这时就已经拿到了相关数据。
接下就是对获取的内容解析和渲染,这部分就是浏览器需要工作的事。
浏览器解析渲染页面分为一下五个步骤:
1.根据 HTML 解析 DOM 树
- 根据 HTML 的内容,将标签按照结构解析成为 DOM 树,DOM 树解析的过程是一个深度优先遍历。即先构建当前节点的所有子节点,再构建下一个兄弟节点。
- 在读取 HTML 文档,构建 DOM 树的过程中,若遇到 script 标签,则 DOM 树的构建会暂停,直至脚本执行完毕。
2.根据 CSS 解析生成 CSS 规则树(CSSOM)
- 解析 CSS 规则树时 js 执行将暂停,直至 CSS 规则树就绪。
- 浏览器在 CSS 规则树生成之前不会进行渲染。
3.结合 DOM 树和 CSS 规则树,生成渲染树
- DOM 树和 CSS 规则树全部准备好了以后,浏览器才会开始构建渲染树。
- 精简 CSS 并可以加快 CSS 规则树的构建,从而加快页面相应速度。
4.根据渲染树计算每一个节点的信息(布局)
- 布局:通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸
- 回流:在布局完成后,发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。
5.根据计算好的信息绘制页面
- 绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。
- 重绘:某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘。
- 回流:某个元素的尺寸发生了变化,则需重新计算渲染树,重新渲染。
需要知道的知识
回流
当Render Tree
中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
会导致回流的操作:
- 页面首次渲染
- 浏览器窗口大小发生改变
- 元素尺寸或位置发生改变
- 元素内容变化(文字数量或图片大小等等)
- 元素字体大小变化
- 添加或者删除可见的
DOM
元素 - 激活
CSS
伪类(例如::hover
) - 查询某些属性或调用某些方法
一些常用且会导致回流的属性和方法:
clientWidth
、clientHeight
、clientTop
、clientLeft
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
scrollWidth
、scrollHeight
、scrollTop
、scrollLeft
scrollIntoView()
、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
重绘
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility
等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
TCP断开链接
当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。
简单小对话,基础了解四次挥手
C:我的信息发完了。
S:好的,我听到了,那我就不再接收你的信息了。
S:我也不需要再给你发信息了(全双工通讯)
C:好的,已经关闭了
- 1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
- 2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
- 4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
- 5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
- 6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
参考文章
从URL输入到页面展现到底发生什么? TCP连接三次握手、关闭四次挥手[常见问题汇总] TCP三次握手四次挥手深刻总结 从输入URL开始建立前端知识体系 浏览器的回流与重绘 (Reflow & Repaint)