当我们在浏览器的地址栏中输入URL到页面渲染,中间具体发生了什么?
- 地址栏输入URL
- DNS解析
- 建立HTTP连接(3次握手)
- 浏览器渲染页面
- 断开连接
地址栏输入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请求。
- 浏览器发起请求前,会根据请求头中的
exprise
和Cache-Control
判断是否命中强缓存,如果命中则从缓存获取资源,不会发送请求。如果没有命中则进行下一步 - 没有命中强缓存,浏览器会发送请求,根据请求头中携带的
if-modified-since
和if-none-match
判断是否命中协商缓存,命中则从缓存中获取资源,否则进行下一步 - 如果前2步都没有命中,则直接从服务端获取资源
浏览器缓存
强缓存
浏览器缓存查找结果,并根据该结果的缓存规则来决定是否使用该缓存的过程
强缓存又分为exprise
和Cache-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
- 浏览器第一次请求该资源时,服务器会在响应头中添加
last-modified
字段,代表着该资源在服务器的最后修改时间 - 浏览器第二次请求时会携带
if-modified-since
字段,值为服务器第一次返回的last-modified
的值 - 服务器收到请求会对比该资源在服务器的的时间,如果相同代表缓存生效,返回304;否则返回最新资源
e-tag和if-none-match
- 浏览器第一次请求该资源时,服务器会在响应头中添加
e-tag
字段,代表该资源的唯一标识 - 浏览器第二次请求时会携带
if-none-match
,值为服务器第一次返回e-tag
的值 - 服务器收到请求会对比该资源的唯一标识,相同代表资源为更新,缓存生效,返回304,;否则返回最新资源
注意:e-tag和last-modified同时存在时,e-tag的优先级更高
注意,虽然这里简单介绍了浏览器缓存,但这并不是说明DNS解析在协商缓存之前,因为协商缓存是要发送HTTP请求的,而此时却还没有建立HTTP连接。
因为当你输入一个URL后,浏览器觉得这个URL曾经可能访问过,所以会先发送一个获取网页的请求。但是请求在发送前会查找缓存,存在缓存的话就会拦截请求并返回缓存,否则就往下进入网络请求过程
DNS解析
众所周知,在发起HTTP请求前会进行域名解析,为的就是解析出网站的IP地址。为什么要获取网站的IP地址呢?因为域名只是为了方便大家记忆,真实情况下还是通过IP地址进行传输的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ij2vYunZ-1662473527700)(C:\Users\86188\Desktop\笔记\图片\DNS.png)]
递归查询
我们的浏览器、操作系统、路由器都会缓存一些URL对应的IP地址,统称为DNS高速缓存。目的就是为了加快DNS解析速度,每次查询不用直接到根域名服务器中去查询。
查询顺序如下:
- 浏览器缓存
- 系统缓存(HOST)
- 路由器缓存
- ISP缓存
迭代查询
局部的DNS服务器并不会自己向其他服务器进行查询,而是将能够解析该域名的服务器的IP地址返回给客户端,让客户端再去查询。客户端会不断的向这些服务器进行查询,直到查询到结果。
建立HTTP连接(3次握手)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Glut5Qvs-1662473527701)(C:\Users\86188\Desktop\笔记\图片\TCP.png)]
- 第一次握手,客户端发送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次挥手)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b7hLzAuD-1662473527701)(C:\Users\86188\Desktop\笔记\图片\TCP_CLOSE.png)]
挥手过程:
- 第一次挥手,客户端发送FIN报文,表示要断开连接。此时客户端处于FIN-WAIT-1状态
- 第二次挥手,服务端收到FIN报文后,会向客户端发送确认ACK,表示已经收到客户端的报文了。此时服务端处于CALOSE-WAIT状态
- 第三次挥手,服务端也想断开连接和,发送FIN报文。此时服务端处于LAST_ACK状态
- 第四次挥手,客户端收到服务端的报文知道可以断开连接了,于是发送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