从输入url到页面完成加载发生了什么(完整版)
在写这篇文章之前本想着这个知识点涉及知识点太多太杂,找一篇大牛写的看看就算了,但是看了大概七八篇后,内心更纠结了——🙃🙃🙃真的好杂。。。记忆点找不到了,搞的心里乱乱的,大概是纠结症犯了。所以还是动手总结一下,让自己有个可以抓取的记忆点,也让自己对这个知识点有个浅显的认知。本文旨在讲述发生的流程,如想深究的可自行度娘哦~,其中穿插的知识点及概念我会放到小框里或者贴参考链接。
先来个流程总述:
- DNS解析:将域名解析成IP地址
- TCP连接:TCP三次握手
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束:TCP四次挥手
1、DNS解析
在浏览器输入URL后,首先要经过域名解析。浏览器通过向 DNS 服务器发送域名,DNS 服务器查询到与域名相对应的 IP 地址,然后返回给浏览器,浏览器再将 IP 地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。
1.什么是URL
URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。比如 http://www.w3school.com.cn/ht...,
遵守以下的语法规则:
`scheme://host.domain:port/path/filename`
各部分解释如下:
scheme:定义因特网服务的类型。常见的协议有 http、https、ftp、file,其中最常见的类型是 http,而 https 则是进行加密的网络传输。
host:定义域主机(http 的默认主机是 www)
domain:定义因特网域名,比如 w3school.com.cn
port:定义主机上的端口号(http 的默认端口号是 80)
path: 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
filename: 定义文档/资源的名称
2. 什么是DNS
DNS(domain name system,域名系统):因特网上域名和IP地址相互映射的分布式数据库;简单理解就是域名与IP地址的对照表,因为域名(如:www.google.com)对于我们而言,更便于记忆,但是机器却不擅长这种表达方式,因此需要将域名转换为IP地址,以便于机器识别, 这便有了DNS。
3. 根域名服务器
根服务器是架设互联网的必须设施,管理互联网的主目录,全球共有13套根域名服务器
4. 递归查询
客户端主机向本地域名服务器的查询是递归查询;所谓递归查询:客户端主机查询的域名地址无法在本地域名服务器中找到,因此本地域名服务器就以DNS客户端的身份向其他根域名服务器发起请求,进行查询,而不是让客户端主机去一直查询;
递归查询的结果要么是返回的IP地址,要么是报错,表示无法查询到地址;
5. 迭代查询
本地域名服务器向根服务器、顶级域名服务器和主机域名服务器发起的查询请求就是迭代的过程,如:本地域名服务器向根服务器发起查询请求,根服务器中会告诉本地域名服务器:”我这里没有你要找的内容,你去顶级域名服务器上找吧“,并将顶级域名服务器的地址返回给本地域名服务器,本地域名服务器接收到后,继续向顶级域名服务器发送请求;顶级域名服务器要么返回ip地址,要么告诉本地域名服务器下一步要向哪个权限域名服务器发送请求,直到找到ip地址或找不到ip返回报错信息,然后信息返回给客户端主机;
下图给出了这两种查询的差别
递归过程:主机→本地DNS服务器→其他DNS服务器(如:我要找一个苹果吃,找到了A,问A有没有,A说我帮你去找B,B可能有,果真B有,然后B将苹果给了A,A再将苹果给我,这就是递归)
迭代过程:本地DNS服务器→根服务器,本地DNS服务器→顶级域名服务器,本地DNS服务器→权限域名服务器;(如:我要找一个苹果,找到了A,A说我也没有,B可能有,你去找B吧;我又找B,B说我也没有,你去找C吧,我又去找C,终于找到了苹果,这就是迭代的过程)
复制代码
2、TCP连接:TCP三次握手
在客户端发送数据之前会发起 TCP 三次握手用以同步客户端和服务端的序列号和确认号,并交换 TCP 窗口大小信息。
说明:
Ack:应答
Fin:结束; 结束会话
Seq: 一个数据段的第一个序列号
SYN: 同步; 表示开始会话请求
复制代码
- 第一次握手:客户端A将标志位SYN置为1,随机产生一个值为seq=X(X的取值范围为=1234567)的数据包到服务器,客户端A进入SYN_SENT状态,等待服务端B确认(第一次握手,由浏览器发起,告诉服务器我要发送请求了);
- 第二次握手:服务端B收到数据包后由标志位SYN=1知道客户端A请求建立连接,服务端B将标志位SYN和ACK都置为1,ack=X+1,随机产生一个值seq=Y,并将该数据包发送给客户端A以确认连接请求,服务端B进入SYN_RCVD状态(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)。
- 第三次握手:客户端A收到确认后,检查ack是否为X+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=Y+1,并将该数据包发送给服务端B,服务端B检查ack是否为Y+1,ACK是否为1,如果正确则连接建立成功,客户端A和服务端B进入ESTABLISHED状态,完成三次握手,随后客户端A与服务端B之间可以开始传输数据了(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)。
为什需要三次握手? 计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。 书中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。 假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。
3、浏览器向web服务器发送HTTP请求
TCP三次握手之后,开始发送HTTP请求报文至服务器(关于HTTP请求报文详解,我单独写了一篇☞传送门
HTTP请求报文格式:请求行+请求头+空行+消息体,请求行包括请求方式(GET/POST/DELETE/PUT)、请求资源路径(URL)、HTTP版本号;
4、服务器处理请求并返回HTTP报文
服务器收到请求后会发出应答,即响应数据。HTTP响应与HTTP请求相似, HTTP响应报文格式:状态行+响应头+空行+消息体,状态行包括HTTP版本号、状态码、状态说明。
5、浏览器解析渲染页面
浏览器拿到响应文本后,解析HTML代码,请求js,css等资源,最后进行页面渲染,呈现给用户。页面渲染一般分为以下几个步骤:
(1)根据HTML文件解析出DOM Tree
(2)根据CSS解析出 CSSOM Tree(CSS规则树)
(3)将 DOM Tree 和 CSSOM Tree合并,构建Render tree(渲染树)
(4)reflow(重排):根据Render tree进行节点信息计算(Layout)
(5)repaint(重绘):根据计算好的信息绘制整个页面(Painting)
6、TCP四次挥手。
当数据传输完毕,需要断开TCP连接,此时发起tcp四次挥手
1、客户端向服务端发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(由浏览器告诉服务器,我请求报文发送完了,你准备关闭吧)2、服务端向客户端发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。(由服务器告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)
3、服务端向客户端发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(由服务器告诉浏览器,我响应报文发送完了,你准备关闭吧)
4、客户端向服务端发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。(由浏览器告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)
简单说就是:
1、A——>B :A告诉B:“我发完了”;
2、B——>A:B告诉A:“好的,我知道你发完了”
3、B——>A:B告诉A:“我收完了”;
4、A——>B:A告诉B:“好的,我知道你发收完了”
后话
以上基本就是在地址栏从输入 URL 到页面加载显示发生的全过程,当然还有很多的细节没有写进去,不过这些知识对于前端来说已经足够了,有兴趣的小伙伴可以自行深究。最后,小生乃前端小白一枚,写文章的最初衷是为了让自己对该知识点有更深刻的印象和理解,写的东西也很小白,文中如有不对,欢迎指正~ 然后就是希望看完的朋友可以点个喜欢,也可以关注一波~ 我会持续输出!