云计算百科
云计算领域专业知识百科平台

【JavaWeb】一张图看懂浏览器请求服务器的流程

大佬精心打造:JavaWeb进阶学习资料》》点击免费获取

目录

一、浏览器工作流程

二、URL链接的解析

三、DNS获得IP过程

三、建立TCP连接

四、发起HTTP请求

五、服务器接受请求和响应

 六、浏览器解析和渲染


一张图看懂DNS域名解析全过程

一、浏览器工作流程

目前主流浏览器有五种——IE、Firefox、Safari、Chrome及Opera,但Firefox、Chrome及Safari,Safari是部分开源的。

浏览器的主要功能是将用户选择得web资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式通常是HTML,也包括PDF、image及其他格式。

用户用URI(UniformResourceIdentifier统一资源标识符)来指定所请求资源的位置。

HTML和CSS规范中规定了浏览器解释html文档的方式,由W3C组织对这些规范进行维护,W3C
是负责制定web标准的组织。

简化流程:

详细流程:

浏览器工作的流程

1. 输入URL(Uniform Resource Locator): 用户在浏览器地址栏中输入要访问的网址或点击链接。

2. DNS解析: 浏览器通过域名系统(DNS)将输入的域名解析为相应的IP地址,以便与服务器建立连接。

3. 建立TCP连接: 使用HTTP协议,浏览器通过TCP(Transmission Control Protocol)与目标服务器建立连接。这是一个三次握手的过程,确保数据可靠地传输。

4. 发起HTTP请求: 浏览器向服务器发送HTTP请求,请求特定的资源,如网页、图像、样式表等。

5. 服务器处理请求: 服务器接收到请求后,根据请求的内容进行相应的处理,可能涉及数据库查询、业务逻辑处理等。

6. 服务器发送HTTP响应: 服务器将处理结果封装在HTTP响应中,并发送回浏览器。

7. 浏览器接收响应: 浏览器接收到服务器的响应后,根据响应头中的信息判断响应类型(HTML、CSS、JavaScript等),并开始处理。

8. 解析HTML: 如果响应内容是HTML,浏览器开始解析HTML文档,构建DOM(Document Object Model)树。

9. 加载外部资源: 浏览器在解析HTML过程中遇到外部资源链接(如CSS、JavaScript、图片等),会发起新的请求去获取这些资源。

10. 执行JavaScript: 如果页面包含JavaScript代码,浏览器会执行这些脚本,可能会修改DOM结构、发送Ajax请求等。

11. 渲染页面: 浏览器根据DOM树和CSS样式表进行页面布局和渲染,最终呈现给用户。

12. 建立持久连接: 浏览器和服务器之间可能会保持持久连接,以便在后续的请求中更快地传输数据。

13. 页面加载完成: 所有资源都被加载和渲染完毕后,页面加载完成,用户可以与页面进行交互。

请求过程图:

二、URL链接的解析

用户在浏览器地址栏中输入要访问的网址(URL),或者点击页面上的链接。

浏览器内部代码将url进行拆分解析。

三、DNS获得IP过程

详细的DNS服务器请求,请参考作者的相关文章一张图看懂DNS域名解析全过程

浏览器使用域名获得的IP地址与目标服务器建立连接,并请求网页内容.

DNS(Domain Name System)解析是将人类可读的域名转换为计算机可理解的IP地址的过程。以下是DNS解析的主要步骤:

本地缓存查找: 浏览器首先会检查本地的DNS缓存,看是否已经解析过这个域名。如果在缓存中找到了对应的IP地址,并且缓存尚未过期,就可以跳过后续的步骤直接使用这个IP地址。

操作系统缓存查找: 如果本地缓存中未找到对应的IP地址,浏览器会检查操作系统的DNS缓存。类似于本地缓存,如果在操作系统缓存中找到了对应的IP地址,就会直接使用。

递归查询: 如果在本地和操作系统缓存中都没有找到对应的IP地址,浏览器将发起一个递归查询。它会向本地配置的DNS服务器发送一个DNS请求,并等待该服务器的响应。

根域查询: 如果本地DNS服务器无法直接提供域名解析,它将向根域名服务器发出请求。根域名服务器负责存储整个DNS层次结构的顶层信息,它返回一个指向顶级域(如.com、.net)的权威域名服务器的IP地址。

顶级域查询: 本地DNS服务器获得顶级域名服务器的IP地址后,将向该服务器发送请求,获取下一级域的权威域名服务器的IP地址。例如,如果域名是example.com,那么顶级域名服务器将返回.com域的权威域名服务器的IP地址。

权限域查询: 本地DNS服务器继续向下查询,直到找到负责目标域的权威域名服务器。每一步都会获取下一级域的权威域名服务器的IP地址。

目标域查询: 本地DNS服务器最终向目标域的权威域名服务器发送请求,获取该域名对应的IP地址。

结果返回: 目标域名服务器将域名对应的IP地址返回给本地DNS服务器,本地DNS服务器再将这个结果返回给浏览器。

本地缓存更新: 本地DNS服务器将刚刚解析的域名和对应的IP地址存储到本地缓存中,以便在下一次相同的解析请求中加速解析过程。

整个过程大体描述如下,其中前两个步骤是在本地电脑内完成的,
后8个步骤涉及到真正的域名解析服务器。

第一步:本地查找

本地电脑会检查浏览器缓存中有没有这个域名对应的解析过的 IP 地址,如果缓存中有,这个解析过程就结束。浏览器缓存域名也是有限制的,不仅浏览器缓存大小有限制,而且缓存的时间也有限制,通常情况下为几分钟到几小时不等,域名被缓存的时间限制可以通过 TTL 属性来设置。这个缓存时间太长和太短都不太好,如果时间太长,一旦域名被解析到的 IP 有变化,会导致被客户端缓存的域名无法解析到变化后的 IP 地址,以致该域名不能正常解析,这段时间内有一部分用户无法访问网站。如果设置时间太短,会导致用户每次访问网站都要重新解析一次域名。

第二步:hosts文件

如果浏览器缓存中没有数据,浏览器会查找操作系统缓存中是否有这个域名对应的 DNS 解析结果。其实操作系统也有一个[域名解析]的过程,在 Linux 中可以通过 / etc/hosts 文件来设置,而在 windows 中可以通过配置 C:\\Windows\\System32\\drivers\\etc\\hosts 文件来设置,用户可以将任何域名解析到任何能够访问的 IP 地址。例如,我们在测试时可以将一个域名解析到一台测试服务器上,这样不用修改任何代码就能测试到单独服务器上的代码的业务逻辑是否正确。正是因为有这种本地 DNS 解析的规程,所以有黑客就可能通过修改用户的域名来把特定的域名解析到他指定的 IP 地址上,导致这些域名被劫持。

第三步:本地 DNS 服务器

前两个过程无法解析时,就要用到我们网络配置中的 "DNS 服务器地址" 了。操作系统会把这个域名发送给这个本地 DNS 服务器。每个完整的内网通常都会配置本地 DNS 服务器,例如用户是在学校或工作单位接入互联网,那么用户的本地 DNS 服务器肯定在学校或工作单位里面。它们一般都会缓存域名解析结果,当然缓存时间是受到域名的失效时间控制的。大约 80% 的域名解析到这里就结束了,后续的 DNS 迭代和递归也是由本地 DNS 服务器负责。

Linux 在这设置:/etc/resolv.conf

windows 在这配置:控制面板 -》网络和共享中心 -》更改适配器设置 -》选中目标适配器右键选择属性 -》Internet 协议版本 4(TCP/IPv4)-》配置 DNS 地址。

第四步:根DNS服务器

如果本地 DNS 服务器仍然没有命中,就直接到根 DNS 服务器请求解析。

第五步:顶级DNS服务器

根 DNS 服务器返回给本地 DNS 域名服务器一个顶级 DNS 服务器地址,它是国际顶级域名服务器,如. com、.cn、.org 等,全球只有 13 台左右。

第六步:顶级DNS服务器

本地 DNS 服务器再向上一步获得的顶级 DNS 服务器发送解析请求。

第七步:Name Server 域名服务器

接受请求的顶级 DNS 服务器查找并返回此域名对应的 Name Server 域名服务器的地址,这个 Name Server 服务器就是我要访问的网站域名提供商的服务器,其实该域名的解析任务就是由域名提供商的服务器来完成。 比如我要访问 www.baidu.com,而这个域名是从 A 公司注册获得的,那么 A 公司上的服务器就会有 www.baidu.com 的相关信息。

第八步:本地DNS接受域名-IP映射关系

Name Server 服务器会查询存储的域名和 IP 的映射关系表,再把查询出来的域名和 IP 地址等等信息,连同一个 TTL 值返回给本地 DNS 服务器。

第九步:本地DNS处理TTL

返回该域名对应的 IP 和 TTL 值,本地 DNS 服务器会缓存这个域名和 IP 的对应关系,缓存时间由 TTL 值控制。

把解析的结果返回给本地电脑,本地电脑根据 TTL 值缓存在本地系统缓存中,域名解析过程结束在实际的 DNS 解析过程中,可能还不止这 10 步,如 Name Server 可能有很多级,或者有一个 GTM 来负载均衡控制,这都有可能会影响域名解析过程。

三、建立TCP连接

浏览器使用HTTP或HTTPS协议,与目标服务器建立TCP连接。这是通过使用服务器的IP地址和端口号来实现的。它为了方便传输,将大块的数据分割成以报文段为单位的数据包进行管理,并为它们编号,方便服务器接收时能准确地还原报文信息。

各个协议的流程图如下:

Http位于应用层,TCP协议位于传输层,IP地址位于网络层

TCP协议通过“三次握手”等方法保证传输的安全可靠。

创建TCP链接(三次握手)

客户端发送一个带有SYN标志的数据包给服务端,在一定的延迟时间内等待接收的回复。服务端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息,最后客户端再回传一个带ACK标志的数据包,代表握手结束,连接成功。

SYN (Synchronize Sequence Numbers)同步序列编号

ACK (Acknowledgement)确认字符

下图也可以这么理解:

客户端:“你好,在家不,有你信件。”—SYN

服务端:“在的。”—–SYN/ACK

客户端:“好嘞。”—–ACK

为什么要三次握手:因为防止服务端接受到过去的链接,实际客户端已经断开了

关闭TCP连接(4次握手)

为了避免服务器与客户端双方的资源占用和损耗,当双方没有请求或响应传递时,任意一方都可以发起关闭请求。与创建TCP连接的3次握手类似,关闭TCP连接,需要4次握手。

上图可以这么理解:

客户端:“兄弟,我这边没数据要传了,咱关闭连接吧。”—-FIN

服务端:“收到,我看看我这边有木有数据了。”—-ACK

服务端:“兄弟,我这边也没数据要传你了,咱可以关闭连接了。”—-FIN

客户端:“好嘞。”—-ACK

为什么要四次挥手:

因为tcp是双全工的,前两次挥手是客户端表示我已经发送完成,后两次是服务端发送完成。

四、发起HTTP请求

HTTP是hypertexttransferprotocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程。客户端连上web服务器后,若想获得web服务器中的某个web资源,需遵守一定的通讯格式,HTTP协议用于定义客户端与web服务器通迅的格式。然后将请求发送给服务器。

Http浏览器请求过程

Http请求响应:

应用层客户端发送HTTP请求

HTTP请求包括请求报头和请求主体两个部分,其中请求报头包含了至关重要的信息,包括请求的方法(GET / POST)、目标url、遵循的协议(http / https / ftp…),返回的信息是否需要缓存,以及客户端是否发送cookie等。

Http请求报文:

浏览器构建HTTP请求,包括请求方法(GET、POST等)、请求头部(包括User-Agent、Accept、Cookies等信息)、请求体(对于POST请求)等。

http响应报文:

报文格式与响应解释:

五、服务器接受请求和响应

当客户端发起一个HTTP请求时,Web容器(例如Tomcat)会拦截该请求并根据请求的URL来确定如何处理它。URL通常包括协议(http://或https😕/)、主机名(域名或IP地址)、端口号(默认是80或443)、路径(URL的一部分,用于定位资源或控制器)、查询参数等。

在基于 Spring 的 Web 应用中,通常会使用 Spring MVC框架。Spring MVC 的核心组件是 DispatcherServlet,它充当了请求的前置控制器。当请求到达时, DispatcherServlet 通过 Handler Mapping 负责分发请求到适当的处理程序(Controller)。

视图阶段(JSP)

用户发送出请求到前端控制器DispatcherServlet
DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet
DispatcherServlet调用HandlerAdapter(处理器适配器)
HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
Controller执行完成返回ModelAndView对象
HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)
ViewReslover解析后返回具体View(视图)
DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)
DispatcherServlet响应用户

前后端分离阶段(接口开发,异步请求)

用户发送出请求到前端控制器DispatcherServlet
DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet
DispatcherServlet调用HandlerAdapter(处理器适配器)
HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
方法上添加了@ResponseBody
通过HttpMessageConverter来返回结果转换为JSON并响应

 六、浏览器解析和渲染

解析
html
构建
dom

->
构建
render

->
布局
render

->
绘制
render
树:

 我们知道浏览器为了体验友好,并不是文档全部都解析才绘制到屏幕上,而是从上至下开始解析html,遇到css会开启线程下载css;解析过程:

1.将HTML构建成一个DOM树(DOM=DocumentObjectModel文档对象模型),DOM树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。
2.将CSS解析成CSS去构造CSSOM树(CSSOM=CSSObjectModel CSS对象模型)
3.根据DOM树和CSSOM来构造RenderingTree(渲染树)。注意:RenderingTree渲染树并不等同于DOM树,因为一些像Header 或display:none的东西就没必要放在渲染树中了。
4.有了RenderTree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。
5.下一步操作称之为Layout,顾名思义就是计算出每个节点在屏幕中的位置layoutrendertree。
6.再下一步就是绘制,即遍历render树,并使用浏览器UI后端层绘制每个节点。

渲染过程:

性能优化中重绘、重排: (1)Reflow(回流/重排):当它发现了某个部分发生了变化影响了布局,渲染树需要重新计算。 (2)Repaint(重绘):改变了某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的repaint,根据元素的新属性重新绘制,使元素呈现新的外观。重绘不会带来重新布局,并不一定伴随重排;Reflow要比Repaint更花 费时间,也就更影响性能。所以在写代码的时候,要尽量避免过多的Reflow。reflow的原因: (1)页面初始化的时候; (2)操作DOM时; (3)某些元素的尺寸变了; (4)如果CSS的属性发生变化了。减少reflow/repaint (1)不要一条一条地修改DOM的样式。与其这样,还不如预先定义好css的class,然后修改DOM的className。 (2)不把DOM结点的属性值放在一个循环里当成循环里的变量。 (3)为动画的HTML元件使用fixed或absoult的position,那么修改他们的CSS是不会reflow的。 (4)千万不要使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。

css注意事项 css选择符是从右到左进行匹配的。所以,#navli我们以为这是一条很简单的规则,秒秒钟就能匹配到想要的元素,所以,会去找所有的li,然后再去确定它的父元素是不是#nav。因此,写css的时候需要注意:dom深度尽量浅。减少inlinejavascript、css的数量。使用现代合法的css属性。不要为id选择器指定类名或是标 签,因为id可以唯一确定一个元素。避免后代选择符,尽量使用子选择符。原因:子元素匹配符的概率要大于后代元素匹配符。后代选择符;#tpp{}子选择符:#tp>p{}避免使用通配符,举一个例子,.mod.hd*{font-size:14px;}根据匹配顺序,将首先匹配通配符,也就是说先匹配出通配符,然后匹配.hd(就是要对dom树上的所有节点进行遍历他的父级元素),然后匹配.mod,这样的性能耗费可想而知.

javascript位置

如果在解析html的时候遇到js会阻塞页面渲染,所以一般我们会将所有的script标签放到页面底部,也就是body闭合标签之前,这能确保在脚本执行前页面已经完成了DOM树渲染。尽可能地合并脚本。页面中的script标签越少,加载也就越快,响应也越迅速。无论是外链脚本还是内嵌脚本都是如此。

采用无阻塞下载JavaScript脚本的方法:

(1)使用script标签的defer、async属性、;
(2)使用动态创建的script元素来下载并执行代码等异步加载等方法;

efer、async区别: defer、async都是异步下载,但是执行时刻不一致;

相同点:

加载文件时不阻塞页面渲染;
使用这两个属性的脚本中不能调用document.write方法;
允许不定义属性值,仅仅使用属性名;

不同点:

html的版本html4.0中定义了defer,html5.0中定义了async;
这将造成由于浏览器版本的不同而对其支持的程度不同;
每一个async属性的脚本都在它下载结束之后立刻执行,同时会在window 的load事件之前执行,所以就有可能出现脚本执行顺序被打乱的情况;
每一个defer属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在document的DOMContentLoaded之前执行;

赞(0)
未经允许不得转载:网硕互联帮助中心 » 【JavaWeb】一张图看懂浏览器请求服务器的流程
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!