小白也能搞懂的从输入URL到页面显示的过程(上)
- 我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情”
- 很早之前就了解过从输入网址到页面显示的过程这道题目,但是感觉找到的博文(可能是我的问题55)都无法满足我想了解的深度和广度,所以我就结合了计网教材啃一啃这个过程

一、构建请求
- 当你在浏览器地址栏输入网站地址并按下回车键后,浏览器会构建请求行
- 请求行由请求方法、URL和HTTP协议版本组成,用空格分隔
- 举例:
GET /index.html HTTP/1.1
二、查找缓存
👉为什么要浏览器缓存
- 通过HTTP协议,在客户端和浏览器建立连接时需要消耗时间,而大的响应需要在客户端和服务器之间进行多次往返通信才能获得完整的响应,这拖延了浏览器可以使用和处理内容的时间。这就增加了访问服务器的数据和资源的成本,因此利用浏览器的缓存机制重用以前获取的数据就变成了性能优化时需要考虑的事情。
👉浏览器缓存的位置
Memory Cache
:基于内存的缓存,读取高效速度快,但是一旦关闭网页,内存就释放了。Disk Cache
:基于磁盘的缓存,容量大,读取慢
浏览器读取的顺序为 Memory Cache ---> Disk Cache
👉Expires 和 Cache-Control
- Expires:是HTTP/1.0的产物,值为服务器返回该请求结果的缓存的到期时间(绝对值,GMT格式)
但是使用Expires判断是否缓存过期是通过客户端时间和Expires的值进行比较,若有一方时间不准确或者非同时区等那么就会有误差
- Cache-Control: 是HTTP/1.1的产物,默认在客户端进行缓存(
private
),通过max-age=xxx
设置缓存时间(相对值),表示缓存内容将在xxx秒后失效- no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
- no-store:直接禁止浏览器缓存数据
- public:可以被所有的用户缓存,包括终端用户和代理服务器
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
优先级高于Expires,也就是说同时存在的时候,Cache-Control生效
👉浏览器缓存策略
-
当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段就是上述说的
Expires
和Cache-Control
-
浏览器缓存分为强制缓存和协商缓存,强制缓存优先于协商缓存进行
-
强制缓存具体过程
- 若存在缓存标识和结果,且尚未过期,则强制缓存生效则直接使用缓存
- 若无缓存标识和结果,则失效,则直接发起请求
- 存在缓存标识和结果,但结果已经过期,则进行协商缓存
-
协商缓存具体过程
- 浏览器携带缓存表示向服务器发起请求,由服务器根据缓存标识决定是否使用缓存
- 协商缓存失效,则重新获取请求,结果返回200
- 协商缓存生效则继续使用缓存,结果返回304
如果没有找到缓存那么我们继续开启下一步
三、DNS解析:
🤜DNS解析的原因
- DNS的全称是
domain name system
,即域名系统 - IP地址:给连接到互联网的每一台主机(或路由器)的每一个接口,分配一个在全世界范围内唯一的32位标识符
- 域名是方便用户记忆的,但并不能被计算机直接识别,计算机只能识别纯数字的IP地址,所以需要进行DNS解析
我们先来了解一下DNS解析中的迭代查询和递归查询,我记得这个在面试中也有问过~
🤜迭代查询和递归查询
- 迭代查询
- 当其他服务器接收到当前服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么跟当前服务器说“下一步应该去××服务器查询”(意思就是说我给你指明了路,你别烦我了)
- 当其他服务器接收到当前服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么跟当前服务器说“下一步应该去××服务器查询”(意思就是说我给你指明了路,你别烦我了)
- 递归查询
- 如果所询问的服务器不知道被查询的域名的IP地址,那么它就以DNS客户的身份,向其他服务器发起查询请求报文(就是替换它进行查询,而不是让它自己去查询-- 速成大冤种)
- 返回的结果为查询的IP地址或是报错表示无法查询到所需的IP地址
🤜DNS解析
- 首先会搜索浏览器的DNS缓存,有则结束
- 去操作系统查找DNS缓存,一般在hosts文件,有则结束
- 到本地域名服务器,本地域名器查找DNS缓存,有则结束返回结果
主机到本地域名服务器一般是递归查询,也就是说本地域名服务器替代了它去查询,我们下面就看本地域名服务器的表演,注意哦,后面的请求一般都是迭代查询了
- 本地域名服务器向根域名服务器发起请求,有则返回所要查询的IP地址,没有则把顶级域名服务器的IP地址返回
- 本地域名服务器向顶级域名服务器发起请求,有则返回所要查询的IP地址,没有则把权限域名服务器的IP地址返回
- 本地域名服务器再向权限域名服务器发起请求,有则返回所要查询的IP地址,没有则把权限域名服务器的IP地址返回
- 就这样进行迭代查询,直到最后知道了要解析的域名的IP地址,然后把这个结果返回给发起查询的主机
注意:以上的迭代查询,是大部分情况,但是是取决于最初的查询报文的设置要求使用哪种查询方式
🤜Other
- DNS服务器是基于UDP的,因此会用到UDP协议
- 简而言之就是将域名解析(转换)为IP地址
四、发起TCP连接
- 解析出IP地址后,根据IP地址和默认端口(HTTP的默认端口是
80
,HTTPS的默认端口是443
),和服务器建立TCP连接
👐TCP是什么
- TCP是面向连接的运输层协议,也就是说程序应用在使用TCP协议之前,必须建立起TCP连接,在数据传输完毕后,必须释放建立的TCP连接(其实有点类似于打电话的过程)
- TCP提供可靠交付的服务。通过TCP连接传送的数据无差错,不丢失,不重复,并且按序到达
- TCP连接是一条虚连接(逻辑连接),不是一条真正的物理连接
👐TCP 三次握手的过程如下
- SYN为首部中的同步位,SYN=1的报文段不能携带数据,但是会消耗掉一个序号
- seq为初始序号
- ack为确认号,该字段存放的信息为期望收到对方下一个报文段的第一个数据字节的序号
- ACK不携带数据则不消化序号,字段ACK=1时,确认号字段才有效
- 客户端发送一个带
SYN=1
,seq=X
的数据包到服务器端口,客户端进入同步已发送状态(第一次握手,由客户端发起,告诉服务器我要发送请求啦) - 服务器发回一个带
SYN=1
,ACK=X+1
,seq=Y
的响应包以示传达确认信息,服务器进入同步收到状态(第二次握手,由服务器发起,告诉客户端我准备接受了,你赶紧发送吧) - 客户端再回传一个带
ACK=Y+1
,Seq=Z
的数据包,代表“握手结束”,客户端进入已建立连接状态,当服务端接收客户端发送的确认后,也进入已建立连接状态(第三次握手,由客户端发送,告诉服务器,我马上就发了,准备接受吧)
你可能会想,两次握手不就已经说明能客户端和服务端发送正常接收正常了吗,为什么还需要第三次握手
👐 为什么A最后还需要再发送一次请求/为什么不能两次握手
- 为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误
- 在两次握手的条件下
- 正常情况: A发出连接请求,但是因为连接请求报文丢失而没有收到确认,所以又重发了一个连接请求报文,这次收到B的回复确认了,那么建立起了正确连接。传输完毕就释放了连接。
- 异常情况:A发出连接请求,但是只是在某些网络节点长时间滞留,以致延误到连接释放以后的某个时间才到达了B,B收到该“失效的连接请求报文”后误以为是A重新发起了连接请求,那么B就发出确认,连接建立。因此B的许多资源就白白浪费了
- 采用三次握手的方法,可以防止上述现象的发生。对于上述异常情况,A不会向B的确认发出确认,那么就避免了这种情况导致的资源浪费
五、发送HTTP请求
✍关于HTTP
- HTTP使用了面向连接的TCP作为运输层协议,保证了数据的可靠传输
- HTTP协议本身是无连接的,也就是说已经建立起通信的双方在交换HTTP报文之前不需要先建立HTTP连接
✍HTTP请求报文结构
- 请求行: 包括
- 请求方法:
GET
、POST
、PUT
、DELETE
、PATCH
、HEAD
、OPTIONS
、TRACE
- URL:由
<协议>://<主机>:<端口>/<路径>?<参数>
组成 - 协议版本:
HTTP/1.1
- 请求方法:
- 请求头
- 空行
- 请求体
六、服务器处理请求并返回HTTP报文
💪HTTP响应报文结构:
- 状态行:包括HTTP版本,状态码,解释状态码的简单短语:
HTTP/1.1 200 OK
- 响应头
- 空行
- 响应体
接下来要上大家伙了,请耐心观看,也属于面试官常考内容撒
💪常见状态码
-
👉 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态码
100
- 继续 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分101
- 切换协议 请求者已要求服务器切换协议,服务器已确认并准备切换
-
👉 2xx(成功)表示成功处理了请求的状态码
200
- 成功 服务器已经成功处理了请求。通常,这表示服务器提供了请求的网页201
- 已创建 请求成功并且服务器创建了新的资源202
- 已接受服务器已接受请求,但尚未处理203
- 非授权信息 服务器已经成功处理了请求,但返回的信息可能来自另一来源204
- 无内容 服务器成功处理了请求,但没有返回任何内容206
- 服务器成功处理了部分GET请求
-
👉3xx(重定向)表示要完成请求,需要进一步操作;通常,这些状态代码用来重定向
300
- 多种选择 针对请求,服务器可执行多种操作。服务器可根据请求者(user agent)选择一项操作,或提供操作列表供请求者选择301
- 永久重定向 请求的网页已永久移动到新位置。服务器返回此响应(对GET或HEAD请求的响应)时,会自动将请求者转到新位置302
- 临时重定向 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求303
- 查看其它位置 请求者应当对不同的位置使用单独的GET请求来检索响应时,服务器返回此代码304
- 未修改 自上次请求后,请求的网页未修改过。服务器返回此响应,不会返回网页的内容
看到304有没有一点熟悉的感觉,是的,我们在一开始的协商缓存有讲过304,不记得的记得回去翻一下
305
- 使用代理 请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理307
- 临时性重定向 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有的位置来进行以后的请求(与303类似,但是307会遵照浏览器标准不会从POST变成GET)
-
👉4xx(请求错误)这些状态码表示请求可能出错,妨碍了服务器的处理
400
- 错误请求 服务器不理解请求的语法401
- 未授权 请求要求身份验证。对于需要登录的网页,服务器可能返回此响应403
- 禁止 服务器拒绝请求404
- 未找到 服务器找不到请求的网页405
- 方法禁用 禁用请求中指定的方法406
- 不接受 无法使用请求的内容特性响应请求的网页407
- 需要代理授权 此状态码与401(未授权)类似,但指定请求者应当授权使用代理408
- 请求超时 服务器等候请求时发生超时410
- 已删除 如果请求的资源已永久删除,服务器就会返回此响应413
- 请求实体过大 服务器无法处理请求,因为请求实体过大,超出了服务器的处理能力414
- 请求的URI过长 请求的URI(通常为网址)过长,服务器无法处理
-
👉5xx(服务器错误)这些状态码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错
500
- 服务器内部错误 服务器遇到错误,无法完成请求501
- 尚未实施 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码502
- 错误网关 服务器作为网关或代理,从上游服务器无法收到无效响应503
- 服务器不可用 服务器目前无法使用(由于超载或者停机维护)。通常,这只是暂时状态504
- 网关超时 服务器作为网关代理,但是没有及时从上游服务器收到请求505
- HTTP版本不受支持 服务器不支持请求中所用的HTTP协议版本 响应头 响应体。
现在请求完啦,前面既然有建立连接,那么就会有释放连接,防止资源的浪费
七、关闭TCP连接
- TCP连接释放的过程是比较复杂的,通过四次挥手释放TCP连接
👋四次挥手的过程
FIN 连接释放报文段首部的终止控制位,即时不携带数据也会消耗掉一个序号
- 第一次挥手: 客户端发送一个
FIN=1
,seq=u
的数据包到服务端,客户端进入终止等待1状态,等待服务端的确认 - 第二次挥手:服务端发回一个带
ack=u+1
,seq=v
,ACK=1
的响应包,服务端进入关闭等待状态,A收到B的确认后进入终止等待2状态
- 此时TCP连接处于半关闭状态,就是说A到B方向的连接释放了,但是如果B想继续发送数据,A还是得接收,也就是说B到A方向的连接并没有释放,而且可能还会持续一段时间
- 等B折腾完了(数据发完了),就开始第三次挥手
- 第三次挥手:服务端发送一个带
FIN=1
,ACK=1
,seq=w
,ack=u+1
的数据包到客户端,服务端进入最后确认状态 - 第四次挥手:客户端回发一个带
ACK=1
,ack=w+1
,seq=u+1
的数据包到服务端,客户端进入时间等待状态
- 小小的总结
- 有ack确认号的时候一定会有ACK=1,这样确认号才会生效
- 在客户端和服务端第一次发送的数据包都有seq,为自己的报文段序号
- ack存放的信息为期望收到对方下一个报文段的第一个数据字节的序号,所以一般都是对方发送过来的seq+1
- 在三次握手阶段,客户端和服务端是你来我回,而在四次挥手阶段,是客服服客
- 在释放阶段,客户端先传FIN=1,先请求释放,等服务端发完也传FIN=1请求释放,但是是服务端是先进入关闭状态,客户端后进入(谁先释放了就谁发FIN)
👋如何真正释放TCP连接
- 如上述,四次挥手后,只是进入了时间等待状态,而不是进入最终释放状态
- 第四次挥手后,还需要经过时间等待计时器2MSL(默认值,TCP允许不同的实现可根据具体情况使用更小的MSL值)后,客户端才能进入CLOSED状态,所以服务端是比客户端更早进入CLOSED状态的
- 时间MSL为最长报文段寿命
👋为什么需要等待2MSL时间
- 为了保证客户端发送的最后一个ACK报文能到达B,这个报文可能会丢失,使B无法进入CLOSED状态,就会超时重传FIN+ACK报文段,接着A重传一次确认,重新开始计时
- 防止前面三次握手的原因所提到的失效的连接请求报文段,等待的时间可以使本连接持续的时间内所产生的报文段都从网络中消失
八、思维图
- 看完可以顺着图回忆一遍
转载自:https://juejin.cn/post/7146854911240568863