当你浏览一个网页时发生了什么?即 浏览网页的详细过程,从输入URL到页面加载发生了什么?

目录

1.首先在浏览器地址栏中输入URL或者域名。

2.电脑开始域名解析:

DNS优化

DNS缓存

DNS负载均衡

DNS为什么同时使用TCP和UDP协议

3.域名解析完毕,电脑开始进行TCP连接。

4.HTTPS/HTTP请求和返回

浏览器对服务器发出HTTP请求报文

服务器处理请求并返回HTTP响应报文

HTTPS过程

5.浏览器解析渲染页面

6.Web优化

总结

 

参(ban)考(运)的文章:

主要参考的文章:

前端经典面试题: 从输入URL到页面加载发生了什么?——https://segmentfault.com/a/1190000006879700

菜鸟教程:https://www.runoob.com
windows DNS缓存查看与清理——https://blog.csdn.net/Wu000999/article/details/91601510
TCP 为什么三次握手而不是两次握手(正解版)——https://blog.csdn.net/lengxiao1993/article/details/82771768
TCP为什么需要3次握手与4次挥手——https://blog.csdn.net/xifeijian/article/details/12777187
DNS同时使用TCP和UDP协议——https://www.jianshu.com/p/cb43e1406d83
HTTP请求行、请求头、请求体详解——https://blog.csdn.net/u010256388/article/details/68491509/

1.首先在浏览器地址栏中输入URL或者域名。


2.电脑开始域名解析

域名解析过程如下:

首先,看查找IP是否是本机。不是再去查询本机hosts文件,如果有对应的IP则进行反馈,然后进行下一步。如果本机Hosts文件不含有,则本机向发出一个DNS请求到本地DNS服务器。

DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果。如果没有,本地DNS服务器还要向DNS根服务器进行查询。

根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器,你可以到域服务器上去继续查询,并给出域服务器的地址。

最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。

  • 以上是DNS域名解析的过程。DNS解析包括两种方式,一种是迭代查询,另一种是迭代查询。下图是递归查询

(1)递归查询

递归查询是一种DNS 服务器的查询模式,在该模式下DNS 服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果DNS 服务器本地没有存储查询DNS 信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机。

(2)迭代查询

DNS 服务器另外一种查询方式为迭代查询,DNS 服务器会向客户机提供其他能够解析查询请求的DNS 服务器地址,当客户机发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户机另一台DNS 服务器地址,客户机再向这台DNS 服务器提交请求,依次循环直到返回查询的结果为止。

上述图片是查找www.Microsoft.com的IP地址过程。首先在本地域名服务器中查询IP地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存在该域名时,本地域名会向com顶级域名服务器发送一个请求,依次类推下去。直到最后本地域名服务器得到Microsoft的IP地址并把它缓存到本地,供下次查询使用。从上述过程中,可以看出网址的解析是一个从右向左的过程: com -> Microsoft.com -> www.Microsoft.com。但是你是否发现少了点什么,根域名服务器的解析过程呢?事实上,真正的网址是www.Microsoft.com.,并不是多打了一个".",这个"."对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,既然是默认情况下,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上,所有网址真正的解析过程为:  . -> .com -> Microsoft.com. -> www.Microsoft.com.  

  • DNS优化

了解了DNS的过程,可以为我们带来哪些?上文中请求到Microsoft的IP地址时,经历了8个步骤,这个过程中存在多个请求(同时存在UDP和TCP请求)。如果每次都经过这么多步骤,是否太耗时间?如何减少该过程的步骤呢?那就是DNS缓存。

  • DNS缓存

DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。

  • 在你的chrome浏览器中输入:chrome://dns/,你可以看到chrome浏览器的DNS缓存。

  • Linux系统缓存主要存在/etc/hosts中。

  • Windows系统通过ipconfig /displaydns查看已有缓存,可能比较大建议通过ipconfig /displaydns > .\dns.txt,保存到文件中查看。

  • DNS负载均衡

不知道大家有没有思考过一个问题: DNS返回的IP地址是否每次都一样?如果每次都一样是否说明你请求的资源都位于同一台机器上面,那么这台机器需要多高的性能和储存才能满足亿万请求呢?其实真实的互联网世界背后存在成千上百台服务器,大型的网站甚至更多。但是在用户的眼中,它需要的只是处理他的请求,哪台机器处理请求并不重要。DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向。大家耳熟能详的CDN(Content Delivery Network)就是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。

 

  • DNS为什么同时使用TCP和UDP协议

  • 先说结论:DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议。

区域传输:
DNS的规范规定了2种类型的DNS服务器,一个叫主DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。

TCP和UDP传输字节的大小:
UDP报文的最大长度为512字节,而TCP则允许报文长度超过512字节。当DNS查询超过512字节时,协议的TC标志出现删除标志,这时则使用TCP发送。通常传统的UDP报文一般不会大于512字节。

区域传送时使用TCP的解析:
1.辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。
2.TCP是一种可靠的连接,保证了数据的准确性。

域名解析时使用UDP协议:
客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向DNS服务器查询的时候使用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包

 

 

3.域名解析完毕,电脑开始进行TCP连接

首先进行三次握手。

第一次握手:客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号(SEQ)X,保存在包头的序列号字段里。

第二次握手:

服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(ACK)设置为客户的SEQ加1以.即X+1。

第三次握手.

客户端再次发送确认包,SYN标志位为0,ACK标志位为1.并且把服务器发来SQE号字+1,放在ACK字段中发送给对方,把服务器发来的ACK字段的序号值放入SEQ字段中。

 

数据传输完毕,电脑和服务器至今断开连接。进行四次挥手。

第一次挥手,A信息发送完毕,A发送FIN和ACK报文,并置发送序号SEQ为X。

第二次挥手,B发送确认报文,并置发送序号SEQ为Y,确认序号为X+1。

第三次挥手,B信息发送完毕,B发送FIN和ACK报文,并置发送序号为Y,确认序号为X+1。

第四次挥手,A发送ACK报文,并置发送序号SEQ为X+1,确认序号ACK为Y+1

注:四次挥手,主动断开方会握有一个被动方的SEQ号,在被动方要求断开时,做ACK用。

 

看到这里就会有疑问了TCP 为什么三次握手而不是两次握手?为什么不是三次挥手或者五次挥手?为什么非要是三次握手和四次挥手呢。so我又开始面向搜索引擎学习了。

为什么是三次握手:

  • 为实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
  • 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认

为什么是四次挥手:

原因是因为tcp是全双工模式接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。

 

 

4.HTTPS/HTTP请求和返回

HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文。但是这个过程中存在一定的风险,HTTP报文是明文,如果中间被截取的话会存在一些信息泄露的风险。那么在进入TCP报文之前对HTTP做一次加密就可以解决这个问题了。HTTPS协议的本质就是HTTP + SSL(or TLS)。在HTTP报文进入TCP报文之前,先使用SSL对HTTP报文进行加密。从网络的层级结构看它位于HTTP协议与TCP协议之间。

HTTPS

浏览器对服务器发出HTTP请求报文

发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。HTTP请求报文是由三部分组成: 请求行请求报头请求正文

服务器处理请求并返回HTTP响应报文

后端从在固定的端口接收到TCP报文开始,这一部分对应于编程语言中的socket。它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。HTTP响应报文也是由三部分组成: 状态码响应报头响应报文

HTTPS过程

HTTPS在传输数据之前需要客户端与服务器进行一个握手(TLS/SSL握手),在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL使用了非对称加密,对称加密以及hash等。具体过程请参考经典的阮一峰先生的博客TLS/SSL握手过程
HTTPS相比于HTTP,虽然提供了安全保证,但是势必会带来一些时间上的损耗,如握手和加密等过程,是否使用HTTPS需要根据具体情况在安全和性能方面做出权衡。

  • HTTP请求报文解剖 

HTTP请求报文由3部分组成(请求行+请求头+请求体): 


下面是一个实际的请求报文: 

 

①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。不过,当前的大多数浏览器只支持GET和POST,Spring 3.0提供了一个HiddenHttpMethodFilter,允许你通过“_method”的表单参数指定这些特殊的HTTP方法(实际上还是通过POST提交表单)。服务端配置了HiddenHttpMethodFilter后,Spring会根据_method参数指定的值模拟出相应的HTTP方法,这样,就可以使用这些HTTP方法对处理方法进行映射了。 

GET和POST两种基本请求方法的区别:
原文地址:https://www.cnblogs.com/logsharing/p/8448446.html
CSDN备用地址:https://blog.csdn.net/qq_37174383/article/details/86687758


②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL。

③是协议名称及版本号。 

④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。 

⑤是报文体,它将一个页面表单中的组件值通过param1=value1&param2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1&param2=value2”的方式传递请求参数。 

对照上面的请求报文,我们把它进一步分解,你可以看到一幅更详细的结构图: 


 

  • HTTP响应报文解剖 

响应报文结构 

HTTP的响应报文也由三部分组成(响应行+响应头+响应体): 



以下是一个实际的HTTP响应报文: 

 

①报文协议及版本; 
②状态码及状态描述; 
③响应报文头,也是由多个属性组成; 
④响应报文体,服务器返回给浏览器的文本信息,通常HTML, CSS, JS, 图片等文件就放在这一部分。

响应状态码 

和请求报文相比,响应报文多了一个“响应状态码”,它以“清晰明确”的语言告诉客户端本次请求的处理结果。 

HTTP的响应状态码由5段组成: 

  • 1xx 消息,一般是告诉客户端,请求已经收到了,正在处理,别急...
  • 2xx 处理成功,一般表示:请求收悉、我明白你要的、请求已受理、已经处理完成等信息.
  • 3xx 重定向到其它地方。它让客户端再发起一个请求以完成整个处理。
  • 4xx 处理发生错误,责任在客户端,如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等。
  • 5xx 处理发生错误,责任在服务端,如服务端抛出异常,路由出错,HTTP版本不支持等。


以下是几个常见的状态码: 

200 OK 
你最希望看到的,即处理成功! 


303 See Other 
我把你redirect到其它的页面,目标的URL通过响应报文头的Location告诉你。 


304 Not Modified 
告诉客户端,你请求的这个资源至你上次取得后,并没有更改,你直接用你本地的缓存吧,我很忙哦,你能不能少来烦我啊! 

404 Not Found 
你最不希望看到的,即找不到页面。如你在google上找到一个页面,点击这个链接返回404,表示这个页面已经被网站删除了,google那边的记录只是美好的回忆。 

500 Internal Server Error 
看到这个错误,你就应该查查服务端的日志了,肯定抛出了一堆异常,别睡了,起来改BUG去吧! 

参考文档:
HTTP状态码:https://www.runoob.com/http/http-status-codes.html              
HTTP 响应头信息:https://www.runoob.com/http/http-header-field.htsml           
HTTP请求方法:https://www.runoob.com/http/http-methods.html
HTTP content-type:https://www.runoob.com/http/http-content-type.html

这里留给HTTP缓存:懒得查了。

 

5.浏览器解析渲染页面

浏览器在收到HTML,CSS,JS文件后,它是如何把页面呈现到屏幕上的?下图对应的就是浏览器渲染的过程。WebKit渲染过程

浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。

JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

浏览器在解析过程中,如果遇到请求外部资源时,如图像,iconfont,JS等。浏览器将重复上述过程下载该资源。请求过程是异步的,并不会影响HTML文档进行加载,但是当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程。原因是因为JS有可能修改DOM结构,这就意味着JS执行完成前,后续所有资源的下载是没有必要的,这就是JS阻塞后续资源下载的根本原因。CSS文件的加载不影响JS文件的加载,但是却影响JS文件的执行。JS代码执行前浏览器必须保证CSS文件已经下载并加载完毕。

6.Web优化

上面部分主要介绍了一次完整的请求对应的过程,了解该过程的目的无非就是为了Web优化。在谈到Web优化之前,我们回到一个更原始的问题,Web前端的本质是什么。我的理解是: 将信息快速并友好的展示给用户并能够与用户进行交互。快速的意思就是在尽可能短的时间内完成页面的加载,试想一下当你在淘宝购买东西的时候,淘宝页面加载了10几秒才显示出物品,这个时候你还有心情去购买吗?怎么快速的完成页面的加载呢?优雅的学院派雅虎给出了常用的一些手段,也就是我们熟悉的雅虎34条军规。这34军规实际上就是围绕请求过程进行的一些优化方式。

如何尽快的加载资源?答案就是能不从网络中加载的资源就不从网络中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即DNS优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。当资源到达浏览器之后,浏览器开始进行解析渲染,浏览器中最耗时的部分就是reflow,所以围绕这一部分就是考虑如何减少reflow的次数。

 

 

 

总结

这是第二次增加这次文章内容,主要是因为看到了一篇好的文章。
simon_woo,这位大佬写的《前端经典面试题: 从输入URL到页面加载发生了什么?》。
我作为搬运工,在搬运的同时搜索了一些大佬没有详细介绍的地方,
当然我也有点烦了,也没有很完善,这是一个太庞大的体系。
如果认真的去查去完善,起码两天时间。
太懒了,明天再说。


第二次编辑时间:2020年3月25日

猜你喜欢

转载自blog.csdn.net/qq_40146082/article/details/99885594