网页从输入url到渲染的过程详解及答疑

本节目录

  • 网页从输入url到渲染的过程
  • 知识点补充
    • DNS 域名解析
    • HTTP 请求和TCP 连接
    • TCP 请求过程中的标识符:SYN,ACK,FIN
    • TCP 连接过程中各状态的含义
    • TCP 三次握手过程
    • TCP 三次握手理解
    • 为什么不是两次握手
    • 三次握手过程中可以携带数据吗
    • TCP 的四次挥手
    • 为啥挥手比握手多一次
    • 客户端在TIME-WAIT状态等待2MSL的时间
    • 服务器端处理HTTP请求
    • HTTP 常用状态码
    • 关于 301 和 302 重定向
    • 重定向原因
    • 浏览器解析HTML文档过程
    • reflow(回流)和repain(重绘)
    • 浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)
    • js是放在html文档末尾的原因

参考一 https://juejin.im/post/5bf23afa6fb9a049be5d1494
参考二 https://github.com/sunyongjian/blog/issues/34
参考三 https://blog.csdn.net/weixin_44460333/article/details/89369316
参考四 https://www.cnblogs.com/Andya/p/7272462.html
参考五 https://juejin.im/post/5bbaa549e51d450e827b6b13
参考六 https://xianyulaodi.github.io/2017/03/22/老生常谈-从输入url到页面展示到底发生了什么

网页从输入url到渲染的过程

  • 1.在浏览器中输入一个URL
  • 2.通过DNS将域名解析成IP地址。域名只是与IP地址的一个映射。域名解析的过程实际是将域名还原为IP地址的过程(如果输入的是IP地址,此步骤省略)
  • 3.根据解析到的IP地址加端口 ,浏览器发起http请求
  • 4.浏览器建立一条与服务器的tcp连接(建立过程:三次握手)
  • 5.浏览器通过tcp的三次握手建立好连接后,便向服务器发送HTTP请求,请求数据包
  • 6.服务器收到并处理HTTP请求,根据请求信息去查找资源,返回响应信息
  • 7.浏览器接收HTTP响应
  • 8.如果报文中的状态码表示请求成功,则接受返回的资源(如HTML文件),至此浏览器已经拿到了一个HTML文档,并为了呈现文档而开始解析。
  • 11.至此浏览器已经拿到了一个HTML文档,并为了呈现文档而开始解析。
  • 12.页面全部渲染结束。
  • 13.四次挥手关掉TCP连接

知识点补充

DNS 域名解析

因为http 是基于tcp连接的,而tcp则是通过ip 地址去识别访问的。DNS 解析就是域名转化成ip 地址的过程。如果url里不包含端口号,则会使用该协议的默认端口号。HTTP协议默认80端口,HTTPS协议默认443端口。

HTTP 请求和TCP 连接

目前大部分的应用层连接都是 HTTP 协议,而 HTTPTCP/IP 承载的,所以这一步先假定是建立的TCP 连接

TCP 请求过程中的标识符:SYN,ACK,FIN

SYN
同步标识,通常用来建立连接。在“三次握手”的前两次出现。

ACK
确认标识,接收端确认接收到数据。

FIN
结束标识。表示双方数据发送完成,跟 SYN 类似,属于行为标识。

TCP 连接过程中各状态的含义

  • LISTEN - 侦听来自远方TCP端口的连接请求;
  • SYN-SENT -在发送连接请求后等待匹配的连接请求;
  • SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
  • ESTABLISHED- 代表一个打开的连接,数据可以传送给用户;
  • FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
  • FIN-WAIT-2 - 从远程TCP等待连接中断请求;
  • CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
  • CLOSING -等待远程TCP对连接中断的确认;
  • LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;
  • TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认;
  • CLOSED - 没有任何连接状态;

TCP 三次握手过程

最初客户端和服务端的TCP进程都处于CLOSED关闭状态,客户端主动打开连接,而服务端被动打开连接。(A、B关闭状态CLOSED——B收听状态LISTEN——A同步已发送状态SYN-SENT——B同步收到状态SYN-RCVD——A、B连接已建立状态ESTABLISHED
三次握手协议指的是在发送数据的准备阶段,服务器端和客户端之间需要进行三次交互:

  • 第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;
  • 第二次握手: 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  • 第三次握手: 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

网页从输入url到渲染的过程详解及答疑_第1张图片
起初A和B都处于CLOSED状态——B创建TCB,处于LISTEN状态,等待A请求——A创建TCB,发送连接请求(SYN=1,seq=x),进入SYN-SENT状态——B收到连接请求,向A发送确认(SYN=ACK=1,确认号ack=x+1,初始序号seq=y),进入SYN-RCVD状态——A收到B的确认后,给B发出确认(ACK=1,ack=y+1,seq=x+1),A进入ESTABLISHED状态——B收到A的确认后,进入ESTABLISHED状态。
TCB传输控制块Transmission Control Block:存储每一个连接中的重要信息,如TCP连接表,到发送和接收缓存的指针,到重传队列的指针,当前的发送和接收序号。

TCP 三次握手理解

  • 第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

  • 第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。

  • 第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

为什么不是两次握手

主要为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。
如A发出连接请求,但因连接请求报文丢失而未收到确认,于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。
A共发出了两个连接请求报文段,其中第一个丢失,第二个到达了B,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接,不采用三次握手,只要B发出确认,就建立新的连接了,此时A不理睬B的确认且不发送数据,则B一致等待A发送数据,浪费资源。

三次握手过程中可以携带数据吗

很多人可能会认为三次握手都不能携带数据,其实第三次握手的时候,是可以携带数据的。也就是说,第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。
对于第三次的话,此时客户端已经处于 established 状态,也就是说,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据页没啥毛病。

TCP 的四次挥手

现在的页面为了优化请求的耗时,默认都会开启持久连接(keep-alive),那么一个TCP连接确切关闭的时机,是这个tab标签页关闭的时候。这个关闭的过程就是著名的四次挥手。关闭是一个全双工的过程,发包的顺序的不一定的。一般来说是客户端主动发起的关闭。

  • 第一次挥手:Client发送一个FIN,用来关闭ClientServer的数据传送,Client进入FIN_WAIT_1状态。
  • -第二次挥手:Server收到FIN后,发送一个ACKClient,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
  • 第三次挥手:Server发送一个FIN,用来关闭ServerClient的数据传送,Server进入LAST_ACK状态。
  • 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACKServer,确认序号为收到序号+1Server进入CLOSED状态,完成四次挥手。

网页从输入url到渲染的过程详解及答疑_第2张图片
起初A和B处于ESTABLISHED状态——A发出连接释放报文段并处于FIN-WAIT-1状态——B发出确认报文段且进入CLOSE-WAIT状态——A收到确认后,进入FIN-WAIT-2状态,等待B的连接释放报文段——B没有要向A发出的数据,B发出连接释放报文段且进入LAST-ACK状态——A发出确认报文段且进入TIME-WAIT状态——B收到确认报文段后进入CLOSED状态——A经过等待计时器时间2MSL后,进入CLOSED状态

为啥挥手比握手多一次

因为当Server端收到Client端SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

客户端在TIME-WAIT状态等待2MSL的时间

MSL :最大报文段生存时间(Maximum Segment Lifetime)
为什么客户端发送ACK之后不直接关闭,而是要等一阵子才关闭。这其中的原因就是,要确保服务器是否已经收到了我们的ACK报文,如果没有收到的话,服务器会重新发FIN报文给客户端,客户端再次收到FIN报文之后,就知道之前的ACK报文丢失了,然后再次发送ACK报文。

至于TIME_WAIT持续的时间至少是一个报文的来回时间。一般会设置一个计时,如果过了这个计时没有再次收到FIN报文,则代表对方成功就是ACK报文,此时处于 CLOSED状态。

正是由于这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B超时重传FIN+ACK报文段,而A能在2MSL时间内收到这个重传的FIN+ACK报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到CLOSED状态,若A在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则B无法正常进入到CLOSED状态

服务器端处理HTTP请求

1.处理的过程大致是把请求的信息解析出来
网页从输入url到渲染的过程详解及答疑_第3张图片
2.根据解析出来的信息去请求资源
3.找到资源后,则构建响应信息,主要包括状态码,响应头,响应报文三个部分。
4.把构建的响应发送给客户端(Web服务器首先传送一些HTTP头信息,然后传送具体内容(即HTTP体信息),HTTP头信息HTTP体信息之间用一个空行分开)

HTTP 常用状态码

1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。

  • 100 Continue
  • 101 Switching Protocols

2xx:成功状态码,表示服务器已成功接收到请求并进行处理。

  • 200 OK 表示客户端请求成功
  • 204 No Content 成功,但不返回任何实体的主体部分
  • 206 Partial Content 成功执行了一个范围(Range)请求

3xx: 重定向状态码,表示服务器要求客户端重定向。

  • 301 Moved Permanently 永久性重定向,响应报文的Location首部应该有该资源的新URL
  • 302 Found 临时性重定向,响应报文的Location首部给出的URL用来临时定位资源
  • 303 See Other 请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源
  • 304 Not Modified 服务器内容没有更新,可以直接读取浏览器缓存
  • 307 Temporary Redirect 临时重定向。与302 Found含义一样。302禁止POST变换为GET,但实际使用时并不一定,307则更多浏览器可能会遵循这一标准,但也依赖于浏览器具体实现

4xx:客户端错误状态码,表示客户端的请求有非法内容。

  • 400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解
  • 401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用
  • 403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
  • 404 Not Found 请求的资源不存在,例如,输入了错误的URL

5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。

  • 500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求
  • 503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常

关于 301 和 302 重定向

301302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这是它们的共同点。
他们的不同在于,301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转,而使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的。

重定向原因

(1)某些注册了多个域名的网站,需要通过重定向让访问这些域名的用户自动跳转到主站点等。
(2)网页被移到一个新地址,这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失
(3)跟搜索引擎排名有关。如果一个页面有两个地址,就像http://www.yy.com/http://yy.com/,搜索引擎会认为它们是两个网站,结果造成每个搜索链接都减少从而降低排名。

浏览器解析HTML文档过程

  • 处理 HTML 标记并构建DOM 树,通过HTML解析器解析HTML文档,构建一个DOM Tree
  • 处理CSS 标记并构建CSSOM 树,通过CSS解析器解析HTML中存在的CSS,构建Style Rules
  • DOMCSSOM合并成一个渲染树(Render Tree)
  • 根据渲染树来布局,Render Tree构建完毕,进入到布局阶段(layout/reflow),将会为每个阶段分配一个应出现在屏幕上的确切坐标。
  • 最后将全部的节点遍历绘制出来后,一个页面就展现出来了。

浏览器在解析html文件时,会"自上而下"加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到请求外部资源时,如图片、外链的CSSiconfont等,请求过程是异步的,并不会影响html文档进行加载。
浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。

reflow(回流)和repain(重绘)

DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain
页面在首次加载时必然会经历reflowrepainreflowrepain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflowrepain

浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)

在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。请求过程是异步的,并不会影响HTML文档进行加载,但是当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程。
这些文件的请求都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等…
静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,而从缓存中直接读取。

js是放在html文档末尾的原因

如果在解析的过程中遇到script的时候,文档的解析将会停止下来,立即解析执行脚本,如果脚本是外部的,则会等待请求完成并解析执行。html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。
因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。
CSS文件的加载不影响JS文件的加载,但是却影响JS文件的执行。JS代码执行前浏览器必须保证CSS文件已经下载并加载完毕。
为了不阻塞页面地呈现,一般会把script脚本放在文档的最后。

你可能感兴趣的:(前端基础)