由于上次面试,没有准备这题,就很尴尬的浅层次回答,使得面试更加的焦灼起来。

所以我先借这次的机会,认真的看看和理解这道题。

我看了很多的文章,得出一些心得,URL的输入到浏览器解析大概经历了以下几个过程。

URL解析

DNS查询

TCP/IP连接

HTTP请求

响应请求

页面渲染

TCP断开链接

URL解析

首先我们要了解的预备知识

URL是统一资源定位符,用来表示是某个资源的地址

URL的组成

URL 主要由 协议域名端口路径查询参数锚点6部分组成!

  1. 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服务器与根域及其子域之间的查询方式是迭代查询

我们先看一张图,看下整个解析过程:

63从输入URL到看到页面发生了什么 - 图1

递归查询

我们的浏览器、操作系统、路由器都会缓存一些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,这时就该建立链接,建立链接就会经历三次握手

63从输入URL到看到页面发生了什么 - 图2

  • 第一次握手:建立连接时,客户端发送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协议中发送到服务器指定端口 请求报文由请求行请求头请求体组成。

63从输入URL到看到页面发生了什么 - 图3

请求行

包含请求方法、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的响应报文也由三部分组成(响应行+响应头+响应体)

63从输入URL到看到页面发生了什么 - 图4

从服务器请求的HTML,CSS,JS文件就放在响应体里面。

状态码,它以“清晰明确”的语言告诉客户端本次请求的处理结果。

1xx:指示信息–表示请求已接收,继续处理。

2xx:成功–表示请求已被成功接收、理解、接受。

3xx:重定向–要完成请求必须进行更进一步的操作。

4xx:客户端错误–请求有语法错误或请求无法实现。

5xx:服务器端错误–服务器未能实现合法的请求。

页面渲染

在这时就已经拿到了相关数据。

接下就是对获取的内容解析和渲染,这部分就是浏览器需要工作的事。

63从输入URL到看到页面发生了什么 - 图5

浏览器解析渲染页面分为一下五个步骤:

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 规则树的构建,从而加快页面相应速度。

63从输入URL到看到页面发生了什么 - 图6

4.根据渲染树计算每一个节点的信息(布局)

  • 布局:通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸
  • 回流:在布局完成后,发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。

5.根据计算好的信息绘制页面

  • 绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。
  • 重绘:某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘。
  • 回流:某个元素的尺寸发生了变化,则需重新计算渲染树,重新渲染。

需要知道的知识

回流

Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

会导致回流的操作:

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见DOM元素
  • 激活CSS伪类(例如::hover
  • 查询某些属性或调用某些方法

一些常用且会导致回流的属性和方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

重绘

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

TCP断开链接

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

简单小对话,基础了解四次挥手

C:我的信息发完了。

S:好的,我听到了,那我就不再接收你的信息了。

S:我也不需要再给你发信息了(全双工通讯)

C:好的,已经关闭了

63从输入URL到看到页面发生了什么 - 图7

  • 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)