计算机网络知识系列一


在网上冲浪的我们,无时无刻都在用着网络,而作为一名程序猿,我们更是每天都和网络打交道,但是和用户不同的是,用户只需要知道如何使用数据和 wifi 即可,而我们开发人员则需要知道网络背后的知识和秘密,无论学习还是求职,计网都是我们绕不开的知识点。本篇将讲解对于一个前端 er 我们应该知道/掌握的计算机网络的相关内容/面试题,让我们一起开始本文的学习吧!!!(tips:万字长文,建议点赞收藏反复观看!!! )

适合读者

  • 计网小白
  • 准备面试的求职者

你将学到

  • 前端日常接触到的计网知识
  • 常见的热门面试题

话不多说,让我们一起往下学习吧!!!

image.png

1.OSI 7 层模型和 TCP/IP 四层模型

image-20221009194652350

各层的基本功能:

  • 应用层:对应于 OSI 参考模型的高层,为用户提供所需要的各种服务,例如:FTP、Telnet、DNS、SMTP

  • 传输层:传输层对应 OSI 模型的传输层,为应用层实体提供端到端的通信功能,保证了数据包顺序传输和完整性,包含两个主要的协议:传输控制协议(TCP)以及用户数据报协议(UDP

  • 网络层:对应 OSI 的网络层,主要用于解决主机到主机的通信问题。注重重新赋予主机一个 IP 地址来完成对主机的寻址,它还负责数据包在多种网络中的路由。该层有三个主要协议:网络协议(IP)、互联网组管理协议(IGMP)和互联网控制报文协议(ICMP

    IP协议是最重要的协议 提供了一个可靠、无连接的数据传递服务

  • 数据链路层:对应 OSI 的数据链路层。它负责监视数据在主机和网络之间的交换。事实上,TCP/IP本身并未定义该层的协议,而由参与互连的各网络使用自己的物理层数据链路层协议,然后与TCP/IP的网络接入层进行连接。地址解析协议ARP)工作在此层,即 OSI 参考模型的数据链路层。

2.常见的请求方法

这里我们先解释一下啥叫幂等操作:无论操作多少次,产生的结果都是一样的(比如 get、put这些,post不是幂等操作)

1.get

  • 用于向服务器请求资源
  • 很多时候可以换成get请求的结果来达到减少网络请求的优化效果
  • 通过将请求参数放入url中向服务器请求, 参数只允许是 ASCII字符(会在历史记录中保存,不安全)
  • 由于浏览器对url长度有限制 所以有时候会影响到get请求发送数据时的长度(由RFC规定而不是浏览器)

2.post

  • post操作不是幂等操作,一般用于向服务器发送提交一些数据(比如登陆注册等)
  • 请求参数放在请求体中,参数支持很多类型(字符串、文件等)
  • 一般不对post请求的结果做缓存,比get安全

3.options

  • 请求 web 服务器告知其支持的功能
  • 通常用于询问服务器支持的方法或者对于特殊资源支持的方法(可以使我们不用实际访问那些资源就可以判定用哪些方式去处理资源)

为什么post请求实际上需要发两次请求

  1. 第一次是options的预检请求,返回 204 状态码

    预检请求可以获取服务器是否支持该实际请求,同时可以检查该请求是否是跨域请求,服务器是否支持跨域

  2. 第二次才是实际的post请求

4.put

  • 向服务器写入数据(类似于更新数据,所以操作多少次结果都是一样的,这一点和post方法不一样)

5.head

  • 只获取响应首部的内容 不会返回实体的内容(相当于get但是只获取响应首部的内容)
  • 可以在未获取实际资源的适合对资源的首部进行检查(判断资源类型、状态码以及资源是否被修改)

6.delete

  • 请求服务器删除请求URL所指定的资源
  • 该操作不一定会被执行(HTTP允许服务器在不通知客户端的情况下撤销DELETE请求)

7.trace

  • 允许客户端在最终将请求发送给服务器时查询最终的请求内容(因为请求内容可能在穿过防火墙、代理、网关和其他一些应用程序的适合被修改)
  • 可用于查看代理和其他应用程序对请求产生的效果
  • TRACE请求中不能带有实体的主题部分

8.connect

  • 在与代理服务器通信时创建 管道, 使用管道去进行通信

9.patch

  • 对资源进行部分修改而不是全部修改

3.HTTP 报文的结构

http报文是简单的格式化数据块,由起始行(说明这个请求/响应要做什么)、首部块(header)以及可选的包含数据的主体部分组成,而报文又能分成 请求报文响应报文两种

1
2
3
4
5
6
7
8
//请求报文
<method> <request-URL> <version> // 方法 | 请求url | http版文
<headers> // 首部
<entity-body> //报文主体
//响应报文
<version> <status> <reason-phrase> //版本 | 状态码 | 处理该请求的原因
<headers>
<entity-body>

image-20221009210018806

起始行的组成较为简单

  • 请求行:包含方法、请求URL以及版本号
  • 响应行:包含版本、状态码以及原因短语

接下来我们重点讲下headerheader分为请求头和响应头

报文首部的结构

报文的首部分为:通用首部、请求首部、响应首部、实体首部以及扩展首部五大主要类。

tips:关于本小节和缓存有关的知识后面的缓存小节集中细讲

1.通用首部

请求报文和响应报文都能使用

  • Connection: 允许客户端和服务器指定与请求/响应连接有关的选项(比如http/1.0使用 Connection: keep-Alive开启持久连接,使用 Connection: close来关闭连接)
  • Date:说明报文的创建时间,可用来判断响应资源是来自于缓存还是源服务器(缓存一般不修改 Date数据)
  • MIME-Versioon:发送端使用的 MIME版本
  • Trailer :如果报文采用了分块传输编码方式,就可 以用这个首部列出位于报文拖挂(trailer)部分的首部集合
  • Transfer-Encoding:告知接收端报文的编码方式
  • Update:发送端可能想要升级的版本或者协议
  • Via:列出了与报文途径的节点的学习(代理、网关)
  • Cache-Control:和缓存有关,后面细讲

2.请求首部

  • Client-Ip:提供了客户端IP地址(较老的客户端或者代理使用的扩展首部 不安全)
  • Form: 客户端的 E-mail 地址
  • Host:接收请求的服务器的主机名和端口号
  • Referer:提供了包含当前请求 URI 的文档的 URL
  • UA-Coloe|CPU|Disp|OS: 提供客户端显示器的相关消息(显示颜色等)
  • User-Agent:告知服务器发起请求的应用程序的名称(较老的网关或代理使用)
  • Accept:告知服务器自己想要啥类型的资源
    • Accept:需要哪些媒体类型
    • Accept-Charset:字符集
    • Accept-Encoding:希望服务器使用的编码方式
    • Accept Language:使用的语言
    • TE:服务器可以使用的扩展传输编码
  • Expect:告知服务器它们需求的某种行为(和100Continue响应码紧密相关)
  • If-Math:如果实体标记与文档当前的实体标记相匹配,就获取这份文档
  • If-Modified-Since: 除非在某个指定的日期之后资源被修改过,否则就限制这个请求
  • If-None-Match:如果提供的实体标记与当前文档的实体标记不相符,就获取文档
  • Range:允许请求资源的部分内容(比如断连继续下载,只下载某部分)
  • If-Range: 允许对文档的某个范围进行条件请求
  • If-Unmodified-Since: 除非在某个指定日期之后资源没有被修改过,否则就限制这个请求
  • Authorization:与身份认证有关
  • Cookie: 与cookie有关(不安全)
  • Cookie2: 说明请求端支持的cookie版本
  • 代理请求首部
    • Max-Forward :在通往源端服务器的路径上,将请求转发给其他代理或网关的最大次 数——与 TRACE 方法一同使用
    • Proxy-Authorization :与 Authorization 首部相同,但这个首部是在与代理进行认证时使用的
    • Proxy-Connection: 与 Connection 首部相同,但这个首部是在与代理建立连接时使用的

3.响应首部

  • Age:告知接收端响应已经产生多久时间了 (HTTP/1.1 规定每个响应中都必须包含一个Age首部)
  • Retry-After:如果资源不可用的话,在此日期或事件重试(和 与 503 Service Unavailable(服务不可用)状态码配合使用,给出客户端 可以重试其请求的具体日期和时间(或者秒数))
  • Accept-Ranges:告知客户端是否接收请求资源的某个范围(设置 Accept-anges:none客户端以后就不会发起范围请求了)
  • Vary:列出了所有客户端的请求首部,服务器可以根据这些首部的内容挑选出最适合的资源版本发送给服务端
  • Proxy-Authenticate:来自代理的客户端的质询列表(类似于 WWW-Authenticate 不过是代理使用)
  • Set-Cookie:设置cookie(不安全)
  • WWW-Authenticate:用于 401 Unauthorized响应 向客户端发布一个质询认证方案

4.实体首部

  • Allow:允许的请求方法
  • Location:告知客户端资源的实际位置(重定向相关)
  • Content-Base:解析主体中的相对URL时使用的基础URL
  • Content-Encoding: 主体使用的编码方式
  • Content-Language:主体使用的语言
  • Content-Length:资源的长度
  • Content-Location:资源的实际位置
  • Content-MD5:服务器用来对报文主体进行报文完整性检查
  • Content-Range:请求资源的某部分时 产生的结果由 Content-Range首部给出 (提供了请请求资源在请求内部的位置以及资源的长度)
  • Content-Type:资源的对象类型
  • ETag:根据资源内容生成的标记值(和缓存有关)
  • Expires:缓存有效的时间,超过这个时间后就要重新获取资源
  • Last-Modified:资源最后一次被修改的时间戳

总结:报文的首部和内容大概就讲完了,接下来贴一下掘金首页的请求和响应数据给大家对应着学习

image-20221009220614717

image-20221009220632618

4.常见的状态码

100-101 处理信息
200-206 请求成功
300-307 重定向
400-417 客户端错误
500-505 服务器错误
  • 100:收到了请求的起始部分,客户端应该继续
  • 101:服务器正切换成客户端Update列出的协议
  • 200:服务器成功处理请求
  • 201:用于创建服务器对象的请求(PUT ),服务器已经有对应的资源了,响应主体中应该包含已创建的资源的 URL 以及 Location中的引用
  • 202:请求已经被接收但是服务器还未执行任何操作
  • 203:如果资源首部包含的信息来自于缓存或者其他节点的副本
  • 204:响应报文中不包含资源的主体部分(比如刷新一个表单页面时使用)
  • 206:成功执行那些只请求部分资源的请求 和Range首部配合使用
  • 300: 如果客户端求一个实际指向多个资源的 URL 时(比如查看某个文档网站想要查看中文文档)此时服务器应该在Location首部中包含首选的 URL
  • 301:资源被永久转移到 Location指向的URL
  • 302:与 301 相似 但是是临时资源,以后的请求还是使用老的 URL
  • 303:告知客户端应该使用另外一个 URL 获取资源(这个 URL 在Location中)
  • 304:客户端可以通过它们所包含的请求首部发起条件请 求。这个代码说明资源未发生过变化
  • 305:必须通过代理访问资源,代理的位置在Location中指出
  • 307:和 301 相似,但是也是临时定位

302、303、307 存在交叉主要是为了适配 http1.0 以及 http1.1(http1.1 中 303 的作用和 http1.0 的 302 作用一样,所以 http1.1 将 307 的作用和 http1.0 的 302 一样 这样可以将 302 留给 http1.0 使用)也就是用 http1.1 使用 307 来取代 302 进行临时重定向,而 http1.0 使用 302 啦临时重定向

服务器要选择适当的重定向状态码放入重定向响应中, 需要查看客户端的 http 版本

  • 400:客户端发送了一个错误的请求
  • 401:需要登录等认证方式
  • 403:服务器拒绝该请求(通常在服务器不想说明拒绝原因的时候使用)
  • 404:找不到资源
  • 406:客户端可以指定参数来说明它们愿意接收什么类型的实体。服务器 没有与客户端可接受的 URL 相匹配的资源时,使用此代码
  • 407:和 401类似 但是是要求代理服务器进行认证
  • 408:请求超时
  • 416:请求报文所请求的是指定资源的某个范围 但是这个范围无效时使用
  • 500:服务器遇到一个妨碍它为请求提供服务的错误时,使用此状态码
  • 501:客户端发起的请求超出服务器的能力范围(比如,使用了服务器不 支持的请求方法)时,使用此状态码
  • 502:作为代理或网关使用的服务器从请求响应链的下一条链路上收到了 一条伪响应(比如,它无法连接到其父网关)时,使用此状态码
  • 503:用来说明服务器现在无法为请求提供服务,但将来可以。如果服务 器知道什么时候资源会变为可用的,可以在响应中包含一个 Retry-After首部

5.讲讲三次握手和四次挥手

这个可以说是面试必问了,在讲这个之前我们先看一些前置知识

我们先来看下TCP头部

image-20221009223447438

这里我们解释下上面几个比较关键的名词

  • 序列号:建立连接时随机生成的初始值,用来解决数据包乱序的问题
  • 确认号:发送端接收到这个确认号可以认为在这个序号以前的数据已经被正常接收,用来解决数据丢包的问题
  • SYN:希望建立连接时发送,设为 1
  • FIN:希望断开连接时使用 设为 1
  • RST:表示出现异常时强制断开连接 设为 1
  • ACK:表示确认号有效 设为 1

1.三次握手

接下来我们就看看三次握手的流程图

image-20221010091540679

我们照着上面的图讲解下这个过程(注意:一定要先弄明白上面SYN/ACK/RST/FIN这几个概念再继续看

  1. 开始时客户端处于close状态,为了建立连接,客户端发送了SYN=1表示想要建立连接,并将随机生成的client_isn(tcp 序列号)一起发送过去
  2. 客户端发送完想要连接的申请后就进入了 SYN_SEND状态等待服务端的回应
  3. 此时服务端处于LiSTEN状态,接收到客户端想要申请连接的请求后,将ACK=client_isn + 1(表明服务端接收到了正确的请求),同时将自身随机产生的 server_isn以及 SYN = 1(确认收到了信息)一起发送过去
  4. 之后服务端就进入了 SYN_RE状态,等待客户端的回应
  5. 客户端接收到了服务端的ACKSYN知道了服务端已经能够正确接收客户端的请求了,于是将服务端发的 server_isn + 1ACK上带出去,表示自己也可以接收到服务器的响应
  6. 服务器接收到客户端的回应后,知道了客户端也可以正确接收自己发出的响应,到这里三次握手的流程就结束了

Q:为什么需要三次握手,两次握手不行吗?

A:我们看下上面的流程,会发现,服务端第一次接收到客户端的SYN之后,知道了客户端想要建立连接,这个时候可以表明客户端是有发送请求的能力的,于是服务器将客户端的 ack=client_isn+1以及SYNserver_isn发送过去,当客户端接收到服务器的ack时,它知道服务器接收到了自己正确的请求连接(到这里两次握手完成,但是这个时候只能保证服务端可以正常接收到客户端的请求,但是服务端还不知道客户端能否正常接收自己的响应,所以就需要第三次握手)第三次握手,客户端将自己收到的 server_isn + 1发送回去,服务端接收到数据后就明白客户端已经可以正确接收到自己的响应了,到这里双方确认互相的请求和响应都能被正常接收,第三次握手结束,整个流程也结束了

2.四次挥手

讲完三次握手,相信大家对于这个过程都有了一个新的认知,接下来我们趁热打铁学习一下四次挥手的过程。老规矩,我们还是先看下整个大概的流程

image-20221010085417706

接下来我们按照上图的流程来讲一下(四次挥手和三次握手不一样,因为三次握手只能客户端发送给服务端,但是四次挥手是双端都能发起,所以这里用发送端和接收端来区别!!!)

  1. 发送端想要断开连接,于是发送 FIN=1 表示想要断开连接
  2. 发送完就进入了 FIN_WAIT_1状态,等待接收端的确认消息
  3. 接收端接收到了发送端的FIN,知道对方想要断开连接,于是先发送 ACK给对方,表示我收到了你的断开请求
  4. 如果接收端也想要断开连接,就会继续发送 FIN=1给发送端,表示:”嘿兄弟,我也想断开请求”
  5. 这个时候当发送端接收到了接收端陆续发来的 ACKFIN后,知道接收端可以知道自己的断开请求同时对方自己也想断开
  6. 这个时候发送端就会发送 ACK=1告诉接收端:“我知道你也想断开请求了,可以断开了”
  7. 接收端接收到服务端的确认 ACK后,便断开了连接,进入了close状态
  8. 发送端在进入TIME_WAIT等待2MSL的时间后也进入了 close 状态(为什么要等待2MSL呢?一个是为了保证接收端可以接收到自己最后一次发的ACK 因为如果对方接收不到ACK的话就会重发FIN 另一个作用是保证在新的连接前残余的数据都清除完毕)

Q:为什么需要四次挥手,三次挥手不行吗?

A:如果我们可以理清楚每次挥手结束都代表啥,那自然可以理解这个问题。比如第一次握挥结束,接收端接收到了发送端的FIN,就知道了发送端想要断开连接,于是它回送了ACK过去,当发送端接收到了返回的ACK,它知道接收端已经接收到了自己断开连接的请求了,这个时候第二次挥手结束,这个时候如果接收端也想断开连接,他就会发送FIN给发送端,当发送端接收到FIN的时候,就明白原来你和我一样,都想断开连接,这个时候第三次挥手结束,但是这个时候还不能断开,因为接收端并不知道发送端能不能知道自己也想要断开连接(这也是为啥发送端要在TIME_WAIT等待的原因,因为接收端收不到ACK确认的时候就会重发FIN)所以需要第四次挥手,也就是发送端发送ACK 表示我已经知道你要断开连接了,可以断开了,当接收端接收到确认的ACK时 明白双方都确认完毕,于是断开连接,这里第四次挥手就结束了。

总结:之所以要三次握手和四次握手,都是为了保证双方都能确认收到自己的请求信息,防止一方关闭了另一方还开着这种情况,其中的关键就是理解 ACK/FIN/SYN/RST的作用是啥,理解了自然就不难了

6.讲讲缓存

我们前端说的本地缓存一般指的是浏览器的本地缓存(webStorage),而本地缓存是我们做性能优化时的一大关注点,接下来我就带大家一起学习下如何利用本地缓存来做性能优化

缓存分类:

1.Memory Cache:再浏览器内存中的缓存,访问优先级最高,访问速度也是最快的(和渲染进程共存,进程关闭就清除缓存,所以有效期比较短)

2.service worker Cache:独立的 js 线程,可实现离线缓存、消息推送等功能

3.Disk Cache:磁盘中的缓存,容量较大,但是相对的访问速度较慢

4.push CacheHTTP2的新特新,优先级最低(前面三种缓存无法命中后才会命中这个)

比如我们现在打开掘金首页的控制台,就可以看到哪些请求是用了缓存的

image.png
(红色框里的就是用了memory cachedisk cache 的)

缓存策略:

浏览器的缓存策略可以分为强缓存协商缓存两种

  • 强缓存: 不用向服务器请求。可以通过设置 HTTP Headerexpriescache-control实现
    • expries: 服务器第一次响应时,会将过期的时间戳写在 expries的请求头中返回,当我们再次请求时,如果本地时间小于 expries的时间戳,就直接去缓存中读取资源
      • 缺点:如果跟改了本地时间,可能会导致缓存失效
    • cache-control: 通过 max-age控制本地资源的有效期,s-maxage控制代理服务器(CDN缓存)的有效期(s-maxage仅在代理服务器中生效,max-age仅在客户端生效),设置成no-store 则表示拒绝一切形式的缓存
      • 缺点:如果更改了本地时间,同样会导致缓存失效,但是解决了 expires会因为客户端和服务器直接时差不一导致的缓存时间不一致的问题

cache-control优先级高于 expries

  • 协商缓存:浏览器需要先向服务器发起请求,在判断是否从本地获取缓存资源。可以通过设置 HTTP HeaderLast-ModifiedETag实现

    • Last-Modified:首次响应时会返回 Last-Modified字段,之后客户端每次请求都会带上 If-Modified-Since的字段(上一次response中的 Last-Modified的值),服务器根据该时间戳和资源在服务器上最后的修改时间是否一致来判断是否使用缓存(返回 304表示使用本地缓存,返回新的 Last-Modified表示不使用缓存)
      • 缺点:如果服务器没有及时感知到文件的变化(比如在毫秒级时间内完成了改动,但是因为 Last-Modified是秒级导致无法感知)
    • ETag:既然上面的 Last-Modified存在着缺点,那 ETag就是他的解决方案(服务器根据文件内容编码生成唯一标识符,可以精确感知文件的变化),首次响应会返回 ETag标识,下一次请求就带上 If-None-Match与服务端进行比较来判断是否使用缓存
      • 缺点:服务端需要额外的开销来生成 ETag标识

Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准。

HTTP 决策

关于 HTTP 请求的决策,这里我们通过Chrome给出的官方流程图来给大家讲解

image.png

接下来我给大家解释下上面的步骤

  1. 考虑资源是否可复用
    1. 如果不可以复用,则直接设置 Cache-Controlno-store表示拒绝一切形式的缓存
    2. 如果可以复用,考虑是否设置成每次都需要向浏览器进行缓存的有效确认
      1. 如果需要,则设置 Cache-Controlno-cache
      2. 如果不需要,则考虑是否可以被代理服务器缓存
        1. 如果可以,设置成 public
        2. 如果不行,设置成 private
    3. 考虑资源有效时长
      1. 设置对应的 max-ages-maxage等值
      2. 最后再设置协商缓存需要用到的 ETagLast-Modified

以上便是对于一个HTTP 请求是否要用缓存以及如何使用缓存的决策过程,我们在考虑是否使用缓存的时候也可以按着这个思路来考虑。

网页刷新对缓存的影响

接下来我们看看网页刷新对各类缓存的影响,帮助大家更好地使用缓存

  • 强制刷新: 直接从服务器请求,跳过强缓存和协商缓存(比如 Ctrl + F5
  • 地址栏回车或正常刷新:跳出强缓存,检查协商缓存
  • 新窗口的 URL 访问: 按照正常的缓存策略,即先检查强缓存

相信看到这里你对于如何使用缓存来优化性能应该有了更深入的了解,赶快动手试试吧!

7.讲讲 DNS

DNS:域名系统,当客户端发送一个 URL 请求时,通过DNS 去解析这个URL对应的IP,这个就是DNS的作用。

  • 一个由分层的DNS服务器实现的分布式数据库
  • 一个使得主机能够查询分布式数据库的应用层协议

我们先看下DNS的层次结构

image-20221010092634078

(图片来源于《计算机网络:自顶向下的方法》)

我们依次解释一下各层的DNS以及作用

我们就拿掘金的首页 https://juejin.cn/来讲解吧

1.根 DNS 服务器

DNS服务器可以管理顶级域 DNS 服务器,也就是说我们可以通过询问根DNS服务器知道这个主机名对应的顶级域DNS服务器的 IP 是多少然后在下一阶段去向顶级域DNS服务器查询(如果有需要的话),像 juejin.cn这个url里的根域名其实是最后面的那个 .

2.顶级域 DNS 服务器

管理下一级的权威DNS服务器,也就是说我们可以通过询问顶级域DNS服务器获知这个主机对应的权威DNS服务器的 ip 然后在下一阶段去查询。像 juejin.cn里面这个 cn就是顶级域名,其他常见的顶级域名还有 com(最常见)、edu(教育机构 比如 gdut.edu)、org(适用于各类组织机构)

3.权威 DNS 服务器

查询权威DNS服务器就可以获取最终的 IP 地址了

DNS 的查询过程

我们先来看下整个大概流程

image-20221010094615749

先给大家解释下本地 DNS 服务器:本地DNS服务器可以说是整个过程的核心成员,你可以把本地服务器当成是代理(当主机发出DNS请求时,该请求会被发送到本地 DNS 服务器,由本地 DNS 服务器去进行后续的各个查询过程)可以理解为你们公司的 ISP、你们学校的 ISP 甚至小区的 ISP 都有属于自己的本地 DNS 服务器。本地 DNS 服务器在DNS 缓存中同样发挥着至关重要的作用

接下来我们解释下上面的流程

  1. 首先我们请求 juejin.cn,将请求转发到本地DNS服务器
  2. 本地DNS服务器将该请求转发至 根DNS服务器
  3. 根DNS服务器接收到了请求,发现了 .cn,于是向本地DNS服务器返回 cn 对应的顶级域DNS服务器的 IP 列表(即我不知道这个的ip,但是顶级DNS服务器可能知道,你去问它们)
  4. 本地DNS服务器于是向上一步返回的列表中的顶级域DNS服务器发送请求
  5. 顶级域DNS服务器注意到了 juejin.cn 于是将对应的权威DNS服务器的 IP 列表发过去(我不知道这个,但是这些权威DNS服务器应该知道)
  6. 本地DNS服务器于是向权威DNS服务器发送请求
  7. 权威DNS服务器查询到了 juejin.cn对应的 ip 地址并返回
  8. 本地DNS服务器将收到的 juejin.cn以及对应的 ip 返回给主机 主机开始真正请求对应的 ip 地址

到这里流程就结束了。我们可以轻松发现,所有的请求都是由本地DNS服务器发出的,而对应的响应也是直接返回给本地DNS服务器(大家经常看到的说什么查询过程是 递归+迭代其实就是主机向本地 DNS 查询的过程是一个递归过程,而本地服务器向每个层次的 DNS 服务器请求的过程是一个迭代的过程)

Q:什么是 DNS 缓存?

A:在 DNS 的查询过程中,当一台 DNS 服务器接收到了一个 DNS 响应,就可以选择将映射缓存到本地,这样下次再请求就可以直接拿出本地缓存的内容,这就可以让我们更快的获取想要的 ip(当 DNS 缓存使用好之后,我们很少会去查询根 DNS 服务器,这大大加快我们的查询速度),同时也应该注意管理 DNS 缓存,在一定时间后清除掉对应的缓存(缓存不是永久存在的,有各自对应的有效时间)

8.讲讲 http 的不同版本

1.HTTP/0.9

HTTP/0.9 是最早的 HTTP 协议,即超文本传输协议,主要用于学术交流等简单功能

特点:

  • 只有一个请求行,没有请求头和请求体
  • 服务器只返回数据,不返回响应头等信息
  • 以 ASCII 字符流传输文件(因为传输的都是 HTML 格式的文件,使用 ASCII 字符流传输最合适)

2.HTTP/1.0

  • 无状态、无连接的协议,默认使用非持久连接
  • 每次请求都需要建立一个 TCP 连接
  • 存在队头阻塞的问题(队头阻塞:下一个请求需要在前一个请求响应到达之后才能发送,如果前一个请求一直不响应到达,就会造成后面的请求阻塞)
  • 不能请求资源的一部分,只能完整请求
  • 使用 If-Modified-Since | Expries控制缓存

3.HTTP/1.1

  • 默认使用持久连接(Connect:keep-alive
  • 通过多个 http 请求复用同一个 TCP 连接来避免每次建立连接的时延
  • 同一个 host 下最多只能共存 6 个 TCP 连接
  • 比起 HTTP/1.0 增加了 ETag| If-Unmodified-Since | If-Match等更多缓存头部字段,支持协商缓存和强缓存
  • 新增了 PUT | HEAD | OPTIONS等请求方法
  • 支持资源的部分请求和范围请求
  • 支持请求管道化(在等待上一个请求响应的同时可以直接发送下一个请求,不需要像 http1.0 一样等待上一个请求响应结果的返回,但是服务器还是按照发送请求的顺序处理请求,所以并不是真正意义上的并行请求)
  • 新增 Host 字段(一个服务器可以创建多个 web 站点)
  • 引入了客户端 Cookie 机制和安全机制
  • 使用 CDN 的实现域名分片机制
  • 仍然存在队头阻塞问题
  • 存在 TCP 慢启动(TCP 连接建立后,会采用一个非常慢的速度去发送数据,然后再慢慢调整至最合适的发送速度,这个过程就是慢启动)

4.HTTP/2.0

  • 可以设置请求的优先级
  • 服务器推送(http2 可以直接将数据提前推送到浏览器,这对首屏速度的优化起了很大的作用)
  • 头部压缩。http/2.0 可以对请求头和响应头进行压缩,提高了请求的速度
  • 引入了数据流。(HTTP/2.0 的数据包不是按序发送的,所以需要对数据包做标记,每个请求或者响应的所有数据包就是一个数据流)
  • 二进制协议:HTTP2.0 中头信息和数据主体都是二进制,这给了我妹分帧的能力,从而实现多路复用
  • 多路复用
    • 同一个域名只开启一条 TCP 连接,所有请求和响应都在上面完成
    • 将数据流以消息的形式发送,消息可以拆分成帧,帧之间可以乱序发送(根据帧首部的流表示来保证接收端重组数据时的顺序)
    • 单个连接可以流通双向数据(可以并行传输互不干扰的请求和响应信息)
    • 解决了队头阻塞的问题,极大地加快了请求的速度和利用率

5.HTTP/3.0(QUIC 协议)

基于 UDP 实现了类似于 TCP 的多路数据流,可靠传输等功能

image-20221010152412160

  • 实现了类似 TCP 的流量控制、传输可靠性的功能,提供了数据包重传、拥塞控制以及其他的一些 TCP 中存在的特性
  • 集成了 TLS 加密功能,可以减少握手所花费的 RTT 个数(三次握手其实是个比较浪费时间的过程)
  • 实现了 HTTP/2 中的多路复用功能,实现了数据流的单独传输,解决了 TCP 中队头阻塞的问题
  • 实现了快速握手功能,这大大提升首页速度

总结

image.png

不知不觉已经写了近一万字了,但是却只写了不到一半的内容,限于篇幅的原因,剩下的内容将在下篇补全,感兴趣的同学可以关注一波持续学习!!!

tips:创作不易,觉得作者写的还不错的可以点赞收藏支持一下呀

下期预告

  • CDN
  • cookie、token、jwt、session
  • 前端安全(XSS | CSRF|SQL 注入 | DOS 攻击)
  • HTTP 和 HTTPS 的区别
  • 加密算法
  • 重定向
  • webSocket
  • 跨域问题

往期推荐


文章作者: olddog
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 olddog !
  目录