经典问题:地址栏敲下回车,发生的事情(有坑)
地址栏内容检测
当用户在地址栏输入内容,会先判断输入的内容是否符合url规则。如果用户输入的是文字,就会调用浏览器默认的搜索引擎,把这个文字作为搜索的关键字来搜索。如果输入的内容是符合url规则的,就作为请求的路径,如果是,但是没有写全,就会补全。
缓存的检测
在准备发请求之前,先查看有没有缓存
很多地方都有缓存
首先是看浏览器中是否有缓存,浏览器有一个用来缓存的线程service worker,如果没有找到就进行下一步,(虽然可能是从其他地方找到的缓存,但是浏览器会显示是从service worker获得的缓存)
然后是从内存中查找,内存的大小有限,能够存储的内容也不多,内存读取数据更快,但持续时间短,页面关闭缓存就被释放了
然后再从硬盘中查找,硬盘的存储空间就比内存的存储空间大的多,绝大多数缓存都是从这里获取的 (我个人以为强缓存就是存在硬盘中的)
当用户第一次发送了请求之后,就会有缓存,页面缓存也好,DNS缓存,服务器在响应的时候设置了响应头中携带的信息
强缓存:设置了强缓存,只要没有过期,就可以直接使用,不用发请求
http1.1 cache-control: max-age 设置缓存的过期时长
http1.0 expires 设置缓存在什么时候过期,(这样设置不是太好,有可能浏览器和服务器的时间不同)
强缓存过期之后,就会验证协商缓存
协商缓存:要先发验证请求,看页面是否有更新,如果有更新就发新请求,如果没有更新,服务器就返回304,表示静态资源没有更新
http1.1 If-None-Match/ E-tag 给每一个版本设置标记,如果页面内容有变化,就有新的tag,在看页面是否变化的时候,就直接看tag是否相同
http1.0 If-Modified-since/ Last-Modified 记录每个版本修改的时间,请求的时候比较页面时间是否在
如果我们按下ctrl + f5,就会设置cache-control:no-cache,pragma:no-cache,让浏览器不经过本地缓存校验,直接发起请求
DNS解析
缓存没有找到,就要进行DNS解析,通过域名找到对应的IP地址
DNS也有缓存,先找本地的缓存hosts文件中,如果本地没有缓存,就要进行DNS解析,客户端向本地DNS服务器发送请求,这个请求是一个UDP方式的,这样更快。如果本地DNS服务器有就返回,如果没有,本地DNS服务器就作为客户,向其他根域名服务器发请求,如果找到就返回。DNS域名解析是一个迭代,递归的过程。
建立TCP连接
排队等待
如果是http2.0就不存在排队等待的问题,但是如果是http1.x可能就需要排队等待
因为http1.0是一个连接发送一次请求,一个域名最多建立6个TCP连接
http1.1虽然是个长连接,但是还是要等前面的发送完了才能发送后面的
三次握手
是建立TCP连接的过程
首先客户端向服务器发送一个建立连接的请求
然后服务端收到之后,就返回一个确认收到的报文
客户端收到这个确认报文之后,就向服务端发送一个收到确认的确认报文
为什么要有三次握手,不是两次,或者四次呢?
因为如果当客户端发出建立连接的请求阻塞在网络中的时候,客户端就会重新发建立连接的请求。当连接已经释放之后,之前阻塞在网络中的建立连接请求才到达,此时,服务器会以为客户端又重新请求建立连接,返回一个确认报文,但是客户端并没有请求建立连接,会忽略这的确认报文。如果是两次握手的话,服务器就以为建立了连接,但是客户端根本就没有发请求,会导致服务器等待,浪费服务器资源。可以是四次握手,但是没有必要多花一次来浪费资源。
发送请求,返回响应
四次挥手
当客户端没有数据发送给服务器之后,就发送一个释放连接的请求,表示客户端已经没有数据发给服务器了。
服务器收到之后就返回一个收到的确认报文。服务端不会马上返回确认报文,要等到服务端把要发送的所有数据发送完之后
客户端等待,服务器的所有数据发送完成之后,就向客户端再发送一个释放连接的报文
客户端收到之后向服务器发送收到的确认报文。对于服务器来说已经结束了
但是客户端还要再等待2MSL的时间,才改变状态为close
为什么要等待?
确保服务器正常收到确认报文,如果没收到的话,服务器会有一个请求重传。只要2MSL时间之内没有收到确认重传,就说明一切正常
为什么是2MSL?
片段在网络中最大的存活时间就是MSL,2MSL就是一个往返的时间,如果经历了2MSL都还没有收到确认
此时浏览器已经收到了响应数据,接下来就是浏览器的行为了
文件类型判断
浏览器请求的内容可能不是html等类型,也可能是下载类型。如果是下载内型,浏览器就会开启一个下载线程,用来进行文件下载
如果类型是Html,就进行页面的渲染
页面渲染
DOM树生成
浏览器收到html文档之后,开始解析,但是他不认识html代码,所以要将html解析成token,对于html来说,分为tag token和 text token
利用栈来判断各节点之间的嵌套关系,如果遇到start tag token就入栈,然后在DOM树中添加一个DOM节点。如果遇到的是text token就直接在DOM树中添加一个文本节点。如果遇到的是 end tag token,就看栈顶是否是对应的start tag token 如果是,start tag token就出栈,表示这个DOM节点解析完成。
cssOM树的生成
css代码也是浏览器不认识的,所以也需要解析,将css解析成stylesheets,这个过程是将css属性值标准化,例如将rem->px等,stylesheets是可以通过脚本document.stylesheets获取的
布局树的生成
DOM树中的所有节点并不是都要渲染到页面,需要DOM树和CSSOM树的结合,才知道哪些节点是会渲染到页面上的,就有了布局树的生成
图层树的生成
根据每个节点的特点,可以区分出某些节点是在一个图层,就有了图层树的生成
图层树中的每个节点就是一个图层
栅格化
图层树生成之后,就根据图层生成绘制指令。根据绘制指令按顺序开始绘制。因为图层很大,就会把图层分成多个图块,每个图层就是一张图片。
栅格化的过程就是图块转化成位图的过程。会先从接近视口的地方开始转化,当所有的位图都生成完之后,会发送一个绘制指令
合成和绘制
最后将几张位图合成为一张图片,最后发送到显卡的后缓冲区中。显示到页面。
显示器显示图像
显示器的刷新频率1秒60次,就是显示器每秒钟要读取显卡前缓冲区的内容60次,并显示到页面。
显卡的作用是生成图像,新生成的图像就写入后缓冲区中,系统会交换前缓冲区和后缓冲区的内容,这样显示器每次读取的都是新的内容
显示器刷新的频率要和显卡更新的频率一致
如若有错,还请指正。
三次握手和四次挥手还要再完善

浙公网安备 33010602011771号