浏览器地址栏输入URL到显示页面发生了什么?
1.用户输入
2.卸载原页面并重定向到新页面
3.处理Service Worker
4.网络请求
5.服务端响应
6.浏览器渲染详细流程
这个过程分为两个部分:网络通信+页面渲染
步骤1:DNS 域名解析(域名解析成ip地址,走UTP协议,因此不会有握手过程):浏览器将 URL 解析出相对应的服务器的 IP 地址
- 本地浏览器的 DNS 缓存中查找
- 再向操作系统DNS缓存发送查询请求
- 再向路由器DNS缓存
- 网络运营商DNS缓存
- 递归搜索,并从 url 中解析出端口号
第一步,浏览器缓存
当用户在浏览器输入 www.baidu.com时 , 浏览器会先检查自己的缓存,如果有这个域名,就与其映射的IP地址建立链接,解析完成!
在地址栏输入 chrome://net-internals/#dns , 可以查看谷歌浏览器的DNS缓存
第二步,本地系统缓存
如果浏览器缓存没找到,就检查本地操作系统的缓存,如果有这个域名,就与其映射的IP地址建立链接,解析完成!
Windows系统的DNS缓存保存在 C:\Windows\System32\drivers\etc\hosts 文件中
第三步,本地域名服务器
如果操作系统缓存中没有找到,则检查本地域名服务器的缓存,如果有这个域名,就与其映射的IP建立链接,解析完成!
本地域名服务器为 IPv4协议中配置的首选DNS服务器
第四步,根域名服务器
如果本地域名服务器缓存中没有找到,则请求根服务器,根服务器会返回一个负责该区域的主服务器的IP
根服务器用来管理互联网的主目录,不存储域名,而是存储负责每个域的解析的域名服务器的地址信息,互联网上所有将域名转化为IP地址的请求,理论上都要经过根服务器
第五步,递归请求主域名服务器
本地域名服务器根据根域名服务器返回的IP地址,链接这个主域名服务器,主域名服务器如果有这个域名,就与其映射的IP建立链接,解析完成!
如果没有这个域名,则递归请求下一级域名服务器,直到找到对应的域名
第六步,缓存并建立链接
主域名服务器将查询到的IP地址返回给本地域名服务器,本地域名服务器缓存域名及其映射的IP , 并通过IP地址与web服务器建立链接,展示网站内容。
至此,解析完成!
步骤2:浏览器与目标服务器建立一条 TCP 连接(三次握手)
(图源网络)
第一次握手:建立连接
。客户端发送SYN包 (syb=n)到 服务器,并进入SYN_SENT状态
,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers
第二次握手:服务器接收syn
包,必须确认客户端的syn
包(ack=n+1
),同时也向客户端发送一个SYN
包(syn=k
);即SYN+ACK包,此时服务器进入SYN_RECV
状态;
第三次握手:客户端接收服务器的SYN+ACK
包,向服务器发送 确认包ACK
(ack=k+1
),发送完毕后,客户端与服务器进入ESTABLISHED(TCP连接成功)
状态,完成三次握手。
步骤3:浏览器向服务器发送一条 HTTP 请求报文
请求分为三部分:请求方法URI协议/版本+请求头(Request Header)+请求正文
(图源网络)
步骤4:服务器返回给浏览器一条 HTTP 响应报文
步骤5:浏览器进行渲染
浏览器解析文档资源并渲染页面流程:
(1)解析html资源,构建DOM Tree
(2)解析css资源,构建CSS Rule Tree
(3)JS通过DOM API和CSS OM API来操作DOM Tree和CSS Tree
(4)解析完成后综合DOM Tree和CSS Tree会生成Render Tree,计算每个元素的位置,这个过程就是回流(layout or reflow)
(5)调用操作系统Native GUI的绘制
(6)页面绘制完成
步骤6:关闭 TCP 连接(四次挥手)
(图源网络)
第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。释放报文首部,FIN=1
,其序列号seq=u
;此时,客户端进入FIN-WAIT-1(终止等待1)状态
。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
第二次挥手:服务器收到连接释放报文,发出确认报文,ACK=1
,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态
。
TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。
这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间
。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态
,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1
,ack=u+1
,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w
,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认
。
第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1
,ack=w+1
,而自己的序列号是seq=u+1
,此时,客户端就进入了TIME-WAIT(时间等待)状态
。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态
。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。