从输入url到页面显示内容的过程发生了什么

本文详细解析了从输入URL到页面显示的整个过程,包括构建请求、强/本地缓存查找、DNS解析、建立TCP连接、发起HTTP请求、协商缓存、获取响应及浏览器如何渲染页面。探讨了HTTP协议的缓存机制、TCP三次握手以及DNS解析等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、构建请求

浏览器通过输入的url来解析要请求的是什么协议,构建请求报文,这里要构建的就是HTTP请求报文。

HTTP请求报文包括报文首部和报文主体,对请求报文来说,报文首部包括请求行各种首部字段;而对响应报文来说,报文首部包括状态行各种首部字段

请求行:GET/HTTP/1.1 (请求方法和相应的协议)

状态行:HTTP/1.1 200 OK (相应的协议和状态码)

各种首部字段:比如Cache-Control和Expires,还有If-No-Match,If-modified-since,Etag等

报文主体:在get请求中没有,post请求中向服务器发出的数据,响应报文中为服务器返回给客户端的内容

(在这部分设置一些相关的字段会影响后面的强缓存和协商缓存)

二、强/本地缓存的查找

通过请求报文,找到本地相应资源的响应报文,查看expires或cache-control来判断是否使用强缓存,在HTTP1.0里面expires优先于cache-control,而在HTTP1.1则相反。

如果缓存资源还没有过期,那么就使用本地缓存的资源,返回状态码304,如果资源已过期,那么接着执行。

(这里可以从expires和cache-control来表明HTTP1.1比HTTP1.0多了什么)

强缓存是根据返回头中的Expires或者Cache-Control两个字段来控制的,都是表示资源的缓存有效时间。

Expires是 http 1.0 的规范,值是一个GMT 格式的时间点字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT 。这个时间点代表资源失效的时间,如果当前的时间戳在这个时间之前,则判定命中缓存。有一个缺点是,失效时间是一个绝对时间,如果服务器时间与客户端时间偏差较大时,就会导致缓存混乱。而服务器的时间跟用户的实际时间是不一样是很正常的,所以 Expires 在实际使用中会带来一些麻烦。

Cache-Control这个字段是 http 1.1 的规范,一般常用该字段的 max-age 值来进行判断,它是一个相对时间,比如

.Cache-Control:max-age=3600 代表资源的有效期是 3600 秒。并且返回头中的 Date 表示消息发送的时间,表示当前资源在 Date ~ Date +3600s 这段时间里都是有效的。不过我在实际使用中常常遇到设置了 max-age 之后,在 max-age 时间内重新访问资源却会返回 304 not modified ,这是由于服务器的时间与本地的时间不同造成的。当然 Cache-Control 还有其他几个值可以设置, 不过相对来说都很少用了:
no-cache 不使用本地缓存。需要使用协商缓存。
no-store直接禁止浏览器缓存数据,每次请求资源都会向服务器要完整的资源, 类似于 network 中的 disabled cache。
public 可以被所有用户缓存,包括终端用户和 cdn 等中间件代理服务器。
private 只能被终端用户的浏览器缓存。
如果 Cache-Control与 Expires 同时存在的话, Cache-Control 的优先级高于 Expires。

三、DNS解析

我们请求的时候,请求的地址是IP地址,所以要将我们写的url地址转换为IP地址,就需要DNS解析。在解析的时候,首先查看本地DNS服务器是否有相应域名对应的IP地址,如果有的话,直接返回请求该IP地址。

如果没有的话,根据该地址向根域名服务器发起请求,获取对应的顶级域名服务器的地址,向该顶级域名服务器发起请求,获得对应的权限域名服务器对应的地址,然后返回最终的IP地址。

返回的时候,不仅会返回到要请求的地方,还将该地址缓存到本地DNS服务器。

四、建立TCP连接

获得对应的IP地址后,就等于我们知道了服务器所在的地方,那么对于HTTP请求来说,下一步就是发起TCP连接了。

首先,我们要进行三次握手建立TCP连接。首先最开始客户端和服务端的TCP进程都处于CLOSED(关闭)状态,由客户端主动打开连接,服务端被动打开连接。

  • 第一次握手:客户端先创建传输控制模块TCB,在建立连接的时候发出连接请求报文段,首部中同步位SYN=1,同时选择一个初始序号seq=x。此时TCP客户进程进入SYN-SENT(同步已发送)状态。
  • 第二次握手:服务端收到连接请求报文段后,如同意确认连接,则向客户端发送确认报文段,在确认报文段中将ACK和SYN都置为1,确认号ack=x+1,同时也要选择一个初始序号seq=y,此时TCP服务器进程进入SYN-RCVD(同步收到)状态
  • 第三次握手:客户进程收到服务端的确认报文段后,还要给服务端发出确认报文,确认报文段的ACK置为1ack=y+1,而自己的序号seq=x+1,客户端进入ESTABLISHED(已建立连接)状态,服务端在收到这个确认报文段后,也进入ESTABLISHED状态

五、发起HTTP请求

在TCP连接建立好之后,就可以从浏览器向服务端发送HTTP请求报文了。准备好HTTP请求报文后,就向服务器发起HTTP请求,然后等待服务器返回响应报文。

六、 协商缓存

在发起HTTP请求后,我们所获取的资源还不一定是最新的资源,要先通过协商缓存来判断是否使用缓存
通过在请求中添加If-Modified-Since字段和If-None-Match字段来向服务器确认当前资源是否继续使用缓存

协商缓存是由服务器来确定缓存资源是否可用。 主要涉及到两对属性字段,都是成对出现的,即第一次请求的响应头带上某个字, Last-Modified 或者 Etag,则后续请求则会带上对应的请求字段 If-Modified-Since或者 If-None-Match,若响应头没有 Last-Modified 或者 Etag 字段,则请求头也不会有对应的字段。

Last-Modified/If-Modified-Since 二者的值都是GMT格式的时间字符串, Last-Modified 标记最后文件修改时间, 下一次请求时,请求头中会带上 If-Modified-Since 值就是 Last-Modified 告诉服务器我本地缓存的文件最后修改的时间,在服务器上根据文件的最后修改时间判断资源是否有变化, 如果文件没有变更则返回 304 Not Modified ,请求不会返回资源内容,浏览器直接使用本地缓存。当服务器返回 304 Not Modified 的响应时,response header 中不会再添加的 Last-Modified 去试图更新本地缓存的 Last-Modified, 因为既然资源没有变化,那么 Last-Modified 也就不会改变;如果资源有变化,就正常返回返回资源内容,新的 Last-Modified 会在 response header 返回,并在下次请求之前更新本地缓存的 Last-Modified,下次请求时,If-Modified-Since会启用更新后的 Last-Modified。

Etag/If-None-Match,值都是由服务器为每一个资源生成的唯一标识串,只要资源有变化就这个值就会改变。服务器根据文件本身算出一个哈希值并通过 ETag字段返回给浏览器,接收到 If-None-Match 字段以后,服务器通过比较两者是否一致来判定文件内容是否被改变。与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于在服务器上ETag 重新计算过,response header中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。

七、获取响应

通过强缓存,协商缓存,最后不管是在缓存,还是在一些缓存的服务器上,又或者是在源服务器上,我们最终拿到了响应资源,将其渲染到页面上。

请求http://www.baidu.com实际上就返回了这样的html文本 如果是在HTTP2.0中,因为有服务端推送的功能,所以可能当我们去请求一个html的时候,会将这个html引用到的css文件和js文件都通过服务端推送到客户端,这样请求的次数也会减少
(如果问的时候没说具体请求什么,这里可以扯一下如果是只请求资源的部分内容的话,可以通过在请求头添加Range来选择要请求哪一部分,顺便扯一下HTTP1.1里新的状态码206)

此外,我们在这里获取到响应报文,还可能得到一个301或302状态码的响应报文。这时网络进程会从响应头的Location字段里面读取重定向的地址,然后再发起新的HTTP或者HTTPS请求,一切又重头开始了
(这里可以尽情扯永久重定向和临时重定向的区别,这里我就不扯了)

这里实际上也可以提一下跨域,上一次我面试的时候被问到请求图片到显示的时候,说了句用img的src属性去得到一张图片不会引起跨域,后来就问了句你刚才说了跨域,说说跨域吧(引导成功.jpg)
(关于跨域的内容包括解决办法可以又写出一篇文章。。。我这里就不扯过多了)

八、浏览器渲染页面(构建DOM树)

因为我们请求的是一个html文件,而实际上,浏览器无法直接理解和使用html,所以需要将其解析为浏览器能理解的解构---DOM树,我们可以试着将下面的这部分html内容来转换成DOM树试试。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值