Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【前端成长之路】从输入URL到页面渲染中间发生了什么 #18

Open
AmamiyaCx opened this issue Sep 6, 2022 · 0 comments

Comments

@AmamiyaCx
Copy link
Owner

AmamiyaCx commented Sep 6, 2022

当我们在浏览器的地址栏中输入URL到页面渲染,中间具体发生了什么?

  1. 地址栏输入URL
  2. DNS解析
  3. 建立HTTP连接(3次握手)
  4. 浏览器渲染页面
  5. 断开连接

地址栏输入URL并解析

URL(Uniform Resource Locator)通常由协议 + 域名 + 端口 + 路径 + 查询参数组成。

比如https://www.baidu.com/search?name=123&age=24

其中https是协议,www.baidu.com是域名,/search是路径,?name=123&age=24是查询参数

解析URL

当我们输入好URL后,浏览器会解析出协议、域名、端口等信息,并发起一个HTTP请求。

  1. 浏览器发起请求前,会根据请求头中的expriseCache-Control判断是否命中强缓存,如果命中则从缓存获取资源,不会发送请求。如果没有命中则进行下一步
  2. 没有命中强缓存,浏览器会发送请求,根据请求头中携带的if-modified-sinceif-none-match判断是否命中协商缓存,命中则从缓存中获取资源,否则进行下一步
  3. 如果前2步都没有命中,则直接从服务端获取资源

浏览器缓存

强缓存

浏览器缓存查找结果,并根据该结果的缓存规则来决定是否使用该缓存的过程

强缓存又分为expriseCache-Control,其中前者为HTTP1.0的产物,后者为HTTP1.1的产物

Exprise
  • 版本:HTTP/1.0
  • 来源:请求头中Exprise(exprise)字段
  • 语法:Expires: Wed, 22 Nov 2019 08:41:00 GMT
  • 缺点:由于某种因素导致服务器的时间和浏览器时间不一致,然后缓存失效
Cache-Control
  • 版本:HTTP/1.1
  • 来源:请求头中Cache-Control(cache-control)字段
  • 语法:cache-control: max-age=604800, public
Cache-Control的值
意思
public 所有内容都被缓存(客户端和代理服务器都能缓存)
private 所有内容只有客户端可以缓存,Cache-Control的默认值
no-cache 客户端缓存内容,但是是否使用该缓存需要进行协商缓存验证
no-store 所有内容都不缓存,即每次都发起HTTP请求向服务器获取资源
max-age 最大缓存时间(秒),缓存内容将在max-age秒后失效

注意:exprise和cache-control同时存在时,cache-control的优先级更高

协商缓存

当强缓存失效,浏览器携带缓存标识想服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。

last-modified和if-modified-since

  1. 浏览器第一次请求该资源时,服务器会在响应头中添加last-modified字段,代表着该资源在服务器的最后修改时间
  2. 浏览器第二次请求时会携带if-modified-since字段,值为服务器第一次返回的last-modified的值
  3. 服务器收到请求会对比该资源在服务器的的时间,如果小于代表缓存生效,返回304;否则返回最新资源

e-tag和if-none-match

  1. 浏览器第一次请求该资源时,服务器会在响应头中添加e-tag字段,代表该资源的唯一标识
  2. 浏览器第二次请求时会携带if-none-match,值为服务器第一次返回e-tag的值
  3. 服务器收到请求会对比该资源的唯一标识,相同代表资源为更新,缓存生效,返回304,;否则返回最新资源

注意:e-tag和last-modified同时存在时,e-tag的优先级更高

注意,虽然这里简单介绍了浏览器缓存,但这并不是说明DNS解析在协商缓存之前,因为协商缓存是要发送HTTP请求的,而此时却还没有建立HTTP连接。

因为当你输入一个URL后,浏览器觉得这个URL曾经可能访问过,所以会先发送一个获取网页的请求。但是请求在发送前会查找缓存,存在缓存的话就会拦截请求并返回缓存,否则就往下进入网络请求过程

DNS解析

众所周知,在发起HTTP请求前会进行域名解析,为的就是解析出网站的IP地址。为什么要获取网站的IP地址呢?因为域名只是为了方便大家记忆,真实情况下还是通过IP地址进行传输的。

DNS

递归查询

我们的浏览器、操作系统、路由器都会缓存一些URL对应的IP地址,统称为DNS高速缓存。目的就是为了加快DNS解析速度,每次查询不用直接到根域名服务器中去查询。

查询顺序如下:

  • 浏览器缓存
  • 系统缓存(HOST)
  • 路由器缓存
  • ISP缓存

迭代查询

局部的DNS服务器并不会自己向其他服务器进行查询,而是将能够解析该域名的服务器的IP地址返回给客户端,让客户端再去查询。客户端会不断的向这些服务器进行查询,直到查询到结果。

建立HTTP连接(3次握手)

TCP

  • 第一次握手,客户端发送SYN=1,并生成一个随机数X发送到服务器,表示要建立连接
  • 第二次握手,服务器收到请求知道客户端要建立连接,向客户端发送SYN=1,ACK=X+1,和生成的随机数Y
  • 第三次握手,客户端搜到服务器发送过来的包,检查SYN=1,并且ACK的值为第一次发送的X+1,如果正确表明服务器已经接受了请求,于是再发送ACK=Y+1,和随机数Z,服务器收到后确定ACK为自己发送的Y+1,表明连接建立成功

为什么需要三次握手

因为三次握手才能确保客户端和服务器双方的接收和发送能力。第一次握手可以确认客户端的发送能力,第二次握手可以确认服务器的接收能力,和发送能力,第三次握手可以确认客户端的接收能力。少了任何一步都可能存在丢包的现象

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

第三次握手时可以携带数据,因为第三次握手对于客户端来说已经建立连接了,并且已经知道服务器接收和发送能力正常了,所以可以发送数据

浏览器渲染页面

渲染过程:

  • 解析下载的HTML生成DOM树,解析下载的CSS生成CSS树
  • DOM树和CSS树合并为渲染树
  • 渲染树根据规则为每个节点生成图形和确定位置
  • 绘制节点
  • GPU渲染页面

断开连接(4次挥手)

TCP_CLOSE

挥手过程:

  1. 第一次挥手,客户端发送FIN报文,表示要断开连接。此时客户端处于FIN-WAIT-1状态
  2. 第二次挥手,服务端收到FIN报文后,会向客户端发送确认ACK,表示已经收到客户端的报文了。此时服务端处于CALOSE-WAIT状态
  3. 第三次挥手,服务端也想断开连接和,发送FIN报文。此时服务端处于LAST_ACK状态
  4. 第四次挥手,客户端收到服务端的报文知道可以断开连接了,于是发送ACK报文,过了一段时间确保服务端能收到发送的报文后进入CLOSED状态。服务端收到客户端的ACK报文后也就关闭连接了,处于CLOSED状态

为什么挥手需要4次

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

为什么客户端发送完ACK之后不能直接关闭,需要等一会?

客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。如果不等待,客户端直接跑路,当服务端还有很多数据包要给客户端发,且还在路上的时候,若客户端的端口此时刚好被新的应用占用,那么就接收到了无用数据包,造成数据包混乱。

参考资料:https://juejin.cn/post/6935232082482298911

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant