【url输入了之后会发生什么?】最细解法,从输入URL到页面渲染的过程
【url输入了之后会发生什么?】最细解法,从输入URL到页面渲染的过程
概述
url输入后响应过程:
输入网址敲回车->查 DNS->找到 IP 地址->通过 TCP 三次握手建立连接->浏览器发送 Http 请求->收到回应->浏览器渲染页面->结束连接
流程可以理解为下图:
输入网址
输入网址的时候,浏览器其实就已经在智能的匹配可能得 url 了,他会从历史记录,书签等,找到已经输入的字符串可能对应的 url,然后给出智能提示,可以补全url地址。
- 浏览器进程检查url,组装协议,构成完整的url,这时候有两种情况:
- 输入的是搜索内容:地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的URL。
- 输入的是请求URL:地址栏会根据规则,给这段内容加上协议,合成为完整的URL;
- 浏览器进程通过 进程间通信(IPC) 把url请求发送给网络进程;
- 网络进程接收到url请求后检查本地缓存是否缓存了该请求资源,如果有则将该资源返回给浏览器进程;
DNS解析
- 准备IP地址和端口:进行DNS解析时先查找缓存,没有再使用DNS服务器解析,查找顺序为:
浏览器缓存
–>本机缓存
–>hosts文件
–>路由器缓存
–>ISP DNS缓存
–>DNS递归查询
|DNS迭代查询
- DNS递归查询
- DNS迭代查询
建立tcp连接
- 拿到域名对应的IP地址之后,浏览器会以一个随机端口(
1024<端口<65535
)向服务器的WEB程序(常用的有nginx等)80端口发起TCP的连接请求。这个连接请求到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接。 - 通过三次握手建立TCP连接过程:
服务器端收到后,也进入ESTABLISHED
状态,由此成功建立了TCP连接,可以开始数据传送;
客户端发送HTPP请求
建立了TCP连接之后,发起一个http请求。一个典型的 http request header
一般需要包括请求的方法,例如 GET
或者 POST
等,不常用的还有 PUT
和 DELETE
、HEAD
、OPTION
以及 TRACE
方法,一般的浏览器只能发起 GET
或者 POST
请求。
客户端向服务器发起http请求的时候,会有一些请求信息,请求信息包含三个部分:
- 方法URL议/版本
- 请求头(Request Header)
请求头包含许多有关的客户端环境和请求正文的有用信息。例如,请求头可以声明浏览器所用的语言,请求正文的长度等。 - 请求正文
请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。请求正文中可以包含客户提交的查询字符串信息。
实例:
GET/sample.jspHTTP/1.1Accept:image/gif.image/jpeg,*/*Accept-Language:zh-cnConnection:Keep-AliveHost:localhostUser-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)Accept-Encoding:gzip,deflateusername=jinqiao&password=1234
服务器处理请求
后端从在固定的端口接收到TCP报文
开始,它会对TCP连接
进行处理,对HTTP协议
进行解析,并按照报文格式进一步封装成HTTP Request
对象,供上层使用。
一些大一点的网站会将你的请求到反向代理服务器中,因为当网站访问量非常大,网站越来越慢,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。
此时,客户端不是直接通过HTTP协议访问某网站应用服务器,而是先请求到Nginx,Nginx再请求应用服务器,然后将结果返回给客户端,这里Nginx的作用是反向代理服务器。同时也带来了一个好处,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。
服务器响应请求
这一步,它会把它的处理结果返回,也就是返回一个HTPP响应。
HTTP响应与HTTP请求相似,HTTP响应也由3个部分构成,分别是:
-
状态行
协议版本:是用http1.0还是其他版本
状态代码:状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。如下:
1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。
2xx:成功状态码,表示服务器已成功接收到请求并进行处理。
3xx:重定向状态码,表示服务器要求客户端重定向。
4xx:客户端错误状态码,表示客户端的请求有非法内容。
5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。状态描述:状态描述给出了关于状态代码的简短的文字描述。比如状态代码为200时的描述为 ok
-
响应头(Response Header)
响应头部:由关键字/值对组成,每行一对,关键字和值用英文冒号":"分隔。 -
响应正文:包含着我们需要的一些具体信息,比如cookie,html,image,后端返回的请求数据等等。
响应正文和响应头之间有一行空格,表示响应头的信息到空格为止,
HTTP/1.1 200 OKDate: Sat, 31 Dec 2005 23:59:59 GMTContent-Type: text/html;charset=ISO-8859-1Content-Length: 122
- 如果是301/302表示服务器已更换域名需要重定向,这时网络进程会从响应头的Location字段里面读取重定向的地址,然后再发起新的HTTP或者HTTPS请求,跳回dns解析。
- 如果是200,就检查Content-Type字段,值为text/html说明是HTML文档,是application/octet-stream说明是文件下载;
tcp连接断开
请求结束,当通用首部字段Conection不是Keep-Alive
时,即不为TCP长连接时,通过四次挥手
断开TCP连接:
- 第一次:客户端(主动断开连接)发送数据包给服务器,其中标志位FIN=1,序号位seq=u,并停止发送数据;
- 第二次:服务器收到数据包后,由于还需传输数据,无法立即关闭连接,先返回一个标志位ACK=1,序号seq=v,确认号ack=u+1的数据包;
- 第三次:服务器准备好断开连接后,返回一个数据包,其中标志位FIN=1,标志位ACK=1,序号seq=w,确认号ack=u+1;
- 第四次:客户端收到数据包后,返回一个标志位ACK=1,序号seq=u+1,确认号ack=w+1的数据包。
浏览器展示html
-
准备渲染进程:浏览器进程检查当前url是否与之前打开了渲染进程的页面的根域名相同,如果相同,则复用原来的进程,如果不同,则开启新的渲染进程;
-
提交文档:
- 渲染进程准备好后,浏览器向渲染进程发起“提交文档”的消息,渲染进程接收到消息后与网络进程建立传输数据的“管道”
- 渲染进程接收完数据后,向浏览器发送“确认提交”
- 浏览器进程接收到确认消息后更新浏览器界面状态:安全状态、地址栏url、前进后退的历史状态、更新web页面
-
在渲染阶段通过渲染流水线在渲染进程的主线程和合成线程配合下,完成页面的渲染
-
先将请求回来的数据解压,随后HTML解析器将其中的HTML字节流通过分词器拆分为一个个Token,然后生成节点Node,最后解析成浏览器识别的DOM树结构。
可以通过Chrome调试工具的Console选项打开控制台输入document查看DOM树; -
构建CSSOM
-
样式计算:转换样式表中的属性值,使其标准化。计算DOM树中每个节点的具体样式,这里遵循CSS的继承和层叠规则;可以通过Chrome调试工具的Elements选项的Computed查看某一标签的最终样式;
-
创建布局树,遍历DOM树中的所有节点,去掉所有隐藏的节点(比如head,添加了display:none的节点),只在布局树中保留可见的节点;
-
计算布局树中节点的坐标位置;
-
对布局树进行分层,并生成分层树(Layer Tree),分层树中每一个节点都直接或间接的属于一个图层(如果一个节点没有对应的层,那么这个节点就从属于父节点的图层)
-
为每个图层生成绘制列表(即绘制指令),并将其提交到合成线程。以上操作都是在渲染进程中的主线程中进行的,提交到合成线程后就不阻塞主线程了;
-
切分图块:合成线程将图层切分成大小固定的图块(256x256或者512x512)然后优先绘制靠近视口的图块,这样就可以大大加速页面的显示速度;
-
栅格化操作
-
合成与显示:
- 合成:一旦所有图块都被光栅化,合成线程就会将它们合成为一张图片,并生成一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。
- 显示:浏览器进程里面有一个叫viz的组件,用来接收合成线程发过来的DrawQuad命令,然后根据DrawQuad命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。
到这里,经过这一系列的阶段,编写好的HTML、CSS、JavaScript等文件,经过浏览器就会显示页面了。
参考博客
一文摸透从输入URL到页面渲染的过程
输入URL全过程