【命运之问】—从输入url到看到页面发送了什么?(上)

前言

这不仅仅是一道高频的面试题,更是成为一个合格的前端工程师所必须掌握的内容。我在阅读很多大佬的有关于这方面知识点的文章下面总能看到有人说学这个只是为了面试,平常工作中完全用不到。可是作为一个每天都需要与浏览器打交道的职业,怎么可能会用不到这方面的知识呢?很简单的一个例子就是“首屏加载”。

chart

web性能的优化与用户留存度息息相关,而不了解浏览器的工作原理怎么能对web性能进行优化呢?这道面试题考的正是我们对于浏览器工作原理的理解。

本篇文章是从浏览器地址栏输入url到请求返回发生了什么?的上篇,主要介绍的是在发送请求到资源返回之间的网络请求相关。

话不多说,开始学习。

流程

在输入url后到返回资源文件,会发生那些事情呢?

看下图

  1. 构建请求
  2. 查找缓存
  3. 准备IP和端口(DNS查询)
  4. 等待TCP连接
  5. 建立TCP连接
  6. 发送HTTP请求
  7. 服务器处理并返回请求
  8. 服务器断开连接

一共八步,为了方便记忆,你可以理解为天龙八“步”。

浏览器端发起 HTTP 请求流程

在正式进入网络请求前,浏览器会对输入的URL进行解析,判断其合法性。

当用户在地址栏中输⼊⼀个查询关键字时,地址栏会判断输⼊的关键字是搜索内容,还是请求的URL

  • 如果是搜索内容,地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的URL。
  • 如果判断输⼊内容符合URL规则,比如输⼊的是baidu.com,那么地址栏会根据规则,把这段内容加上协议,合成为完整的URL,如www.baidu.com/。

请在这里设想一下,如果你在浏览器地址栏里键入百度网站的地址:www.baidu.com, 那么接下来,浏览器会完成哪些动作呢?下面我们就一步一步详细“追踪”下。

构建请求

首先,浏览器构建请求行信息(如下所示),构建好后,浏览器准备发起网络请求。

GET /index.html HTTP1.1
复制代码

查找缓存

在真正发起网络请求之前,浏览器会先在浏览器缓存中查询是否有要请求的文件。其中,浏览器缓存是一种在本地保存资源副本,以供下次请求时直接使用的技术

当浏览器发现请求的资源已经在浏览器缓存中存有副本,它会拦截请求,返回该资源的副本,并直接结束请求,而不会再去源服务器重新下载。这样做的好处有:

  • 缓解服务器端压力,提升性能(获取资源的耗时更短了);
  • 对于网站来说,缓存是实现快速资源加载的重要组成部分。

当然,如果缓存查找失败,就会进入网络请求过程了。

准备 IP 地址和端口

由于我们输入的是域名,而数据包是通过IP地址传给对方的。因此我们需要得到域名对应的IP地址。这个过程需要依赖一个服务系统,这个系统将域名和 IP 一一映射,我们将这个系统就叫做DNS(域名系统)。得到具体 IP 的过程就是DNS解析。

当然,值得注意的是,浏览器提供了DNS数据缓存功能。即如果一个域名已经解析过,那会把解析的结果缓存下来,下次处理直接走缓存,不需要经过 DNS解析

另外,如果不指定端口的话,默认采用对应的 IP 的 80 端口。

等待 TCP 队列

现在已经把端口和 IP 地址都准备好了,那么下一步是不是可以建立 TCP 连接了呢?

答案不一定的,这个得根据不同的浏览器来规定的,我们以Chrome浏览器为例,Chrome 有个机制,同一个域名同时最多只能建立 6 个 TCP 连接,如果在同一个域名下同时有 10 个请求发生,那么其中 4 个请求会进入排队等待状态,直至进行中的请求完成。

当然,如果当前请求数量少于 6,会直接进入下一步,建立 TCP 连接。

建立 TCP 连接

  1. 通过三次握手(即总共发送3个数据包确认已经建立连接)建立客户端和服务器之间的连接。
  2. 进行数据传输。这里有一个重要的机制,就是接收方接收到数据包后必须要向发送方确认, 如果发送方没有接到这个确认的消息,就判定为数据包丢失,并重新发送该数据包。当然,发送的过程中还有一个优化策略,就是把大的数据包拆成一个个小包,依次传输到接收方,接收方按照这个小包的顺序把它们组装成完整数据包。
  3. 断开连接的阶段。数据传输完成,现在要断开连接了,通过四次挥手来断开连接。

读到这里,你应该明白 TCP 连接通过什么手段来保证数据传输的可靠性,一是三次握手确认连接,二是数据包校验保证数据到达接收方,三是通过四次挥手断开连接。

当然,如果再深入地问,比如为什么要三次握手,两次不行吗?第三次握手失败了怎么办?为什么要四次挥手等等这一系列的问题,涉及计算机网络的基础知识,比较底层,但是也是非常重要的细节,希望你能好好研究一下,另外这里有一篇不错的文章,点击进入相应的推荐文章,相信这篇文章能给你启发。

发送 HTTP 请求

现在TCP连接建立完毕,浏览器可以和服务器开始通信,即开始发送 HTTP 请求。浏览器发 HTTP 请求要携带三样东西:请求行请求头请求体

首先,浏览器会向服务器发送请求行,关于请求行, 我们在这一部分的第一步就构建完了,贴一下内容:

// 请求方法是GET,路径为根路径,HTTP协议版本为1.1
GET / HTTP/1.1
复制代码

结构很简单,由请求方法请求URIHTTP版本协议组成。

同时也要带上请求头,比如我们之前说的Cache-ControlIf-Modified-SinceIf-None-Match都由可能被放入请求头中作为缓存的标识信息。当然了还有一些其他的属性,列举如下:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Cookie: /* 省略cookie信息 */
Host: www.baidu.com
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
复制代码

最后是请求体,请求体只有在POST方法下存在,常见的场景是表单提交

服务器处理请求

HTTP 请求到达服务器,服务器进行对应的处理。最后要把数据传给浏览器,也就是返回网络响应。

跟请求部分类似,网络响应具有三个部分:响应行响应头响应体

响应行类似下面这样:

HTTP/1.1 200 OK
复制代码

HTTP协议版本状态码状态描述组成。

响应头包含了服务器及其返回数据的一些信息, 服务器生成数据的时间、返回的数据类型以及对即将写入的Cookie信息。

举例如下:

Cache-Control: no-cache
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Wed, 04 Dec 2019 12:29:13 GMT
Server: apache
Set-Cookie: rsv_i=f9a0SIItKqzv7kqgAAgphbGyRts3RwTg%2FLyU3Y5Eh5LwyfOOrAsvdezbay0QqkDqFZ0DfQXby4wXKT8Au8O7ZT9UuMsBq2k; path=/; domain=.baidu.com
复制代码

服务器断开连接

一般情况下,服务器发送完数据后,就要关闭TCP连接。不过有一种情况比较特殊,我们来看看

Connection:Keep-Alive
复制代码

如果浏览器或者在服务器中加入其头信息如上面的字段的话,TCP连接会仍然保持,这样子浏览器就可以通过同一个TCP连接发送请求,保存TCP连接可以省下去下次请求需要建立连接的时间,提升资源加载速度。

重定向

我们还得聊一聊一种特殊的情况,不过这个情况跟之前提过的状态码有关,我们大概知道了,服务器返回的状态码不同,会有不同的返回的结果,你肯定遇到过这样子的情况吧:当你在浏览器中打开 baidu.com 后,你会发现最终打开的页面地址是 www.baidu.com ** 这两个URL不一样的原因就是涉及到了重定向**,让我们从一张图片上面看看这种情况吧?

服务器返回响应行和响应头(含重定向格式)

我们看看响应行返回的状态码301,状态301告诉浏览器,你需要重新转到另外一个网址,需要重定向的地址正式包含在响应头的Location字段中。接下啦,浏览器获取Location字段中的地址,重新导航,这也就是完整的重定向的执行流程。

这解释了为什么输入baidu.com后,最终打开的是www.baidu.com

涉及面试题

  • 为什么很多站点第二次打开速度会很快??
  • 当登录过一个网站之后,下次再访问该站点,就已经处于登录状态了,这是怎么做到的呢?
  • 如何使用 Cookie 来进行状态管理,说一说流程
  • TCP建立连接过程讲一讲,为什么握手需要三次?
  • UDP了解吗,与TCP相比,优点是啥,缺点呢?
  • 你刚刚说了TCP连接会存在TCP队列,那加载大量图片或者其他资源的时候,该怎么解决卡顿呢

为什么很多站点第二次打开速度会很快??

当然是因为耗时的数据被缓存了呀,首先端口和IP会被缓存,页面资源也会缓存。而不用进行DNS查询甚至对于一些资源请求都不用发送直接从本地拿,那打开速度当然快啦。

当登录过一个网站之后,下次再访问该站点,就已经处于登录状态了,这是怎么做到的呢?

首先映入脑海的当然是Cookie的存在啦,HTTP是无状态的协议,而Cookie的出现弥补HTTP状态管理上的不足

如何使用 Cookie 来进行状态管理,说一说流程

  1. 客户端请求服务端
  2. 服务端生成Cookie信息使用 Set-Cookie 添加到响应报文头部上
  3. 客户端在拿到之后保存Cookie
  4. 在下次请求的时候通过把信息写入请求报文头部Cookie字段中传给服务端

TCP建立连接过程讲一讲,为什么握手需要三次?

建立过程就不讲了,网上答案一大堆,为什么要握手三次呢?为的是确保客户端和服务端的请求响应能力都正常

UDP了解吗,与TCP相比,优点是啥,缺点呢?

你刚刚说了TCP连接会存在TCP队列,那加载大量图片或者其他资源的时候,该怎么解决卡顿呢?

解决方法一:并发连接,就是一个域名多开几个连接同时进行请求。这个浏览器以及帮我们实现了。

解决方法二:域名分片:多创建几个子域名,这样连接就更多了。

解决方法三:使用HTTP2。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享