2021最常见的网络原理面试题好文收藏

Posted linux大本营

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021最常见的网络原理面试题好文收藏相关的知识,希望对你有一定的参考价值。

推荐视频:

腾讯游戏面试必问的UDP可靠性设计

腾讯T2.3亲身经历分享,腾讯offer的获取之路及linux后台开发学习路线

c/c++ linux服务器开发学习地址:c/c++ linux后台服务器高级架构师

1.如何理解 URI?

URI, 全称为(Uniform Resource Identifier), 也就是统一资源标识符,它的作用很简单,就是区分互联网上不同的资源。但是,它并不是我们常说的网址, 网址指的是URL, 实际上URI包含了URN和URL两个部分,由于 URL 过于普及,就默认将 URI 视为 URL 了。
URI 的结构
URI 真正最完整的结构是这样的
在这里插入图片描述
好像跟平时见到的不太一样!先别急,来一一拆解。scheme 表示协议名,比如http, https, file等等。后面必须和://连在一起。user:passwd@ 表示登录主机时的用户信息,不过很不安全,不推荐使用,也不常用。host:port** 表示主机名和端口。path 表示请求路径,标记资源所在位置。query 表示查询参数,为key=val这种形式,多个键值对之间用&隔开。fragment 表示 URI 所定位的资源内的一个锚点**,浏览器可以根据这个锚点跳转到对应的位置。
https://www.baidu.com/s?tn=54093922_6_hao_pg&ie=utf-8&wd=%E7%99%BE%E5%BA%A6
这个 URI 中

  • https 即scheme部分
  • www.baidu.com 为host:port部分(注意,http 和 https 的默认端口分别为80、443)
  • kenguba/upkpls/gisxr2 为path部分
  • word=1&name=kenguba 表示query部分
  • #UrkH4 就是锚点

在这里插入图片描述

URI 编码
URI 只能使用 ASCII , ASCII 之外的字符是不支持显示的,而且还有一部分符号是界定符,如果不加以处理就会导致解析出错。因此,URI 引入了编码机制,将所有非 ASCII 码字符和界定符转为十六进制字节值,然后在前面加个%。

encodeURI("https://www.yuque.com/kenguba/upkpls/gisxr2?name=一缕清风")
"https://www.yuque.com/kenguba/upkpls/gisxr2?name=%E4%B8%80%E7%BC%95%E6%B8%85%E9%A3%8E"
decodeURI("https://www.yuque.com/kenguba/upkpls/gisxr2?name=%E4%B8%80%E7%BC%95%E6%B8%85%E9%A3%8E")

encodeURIComponent("https://www.yuque.com/kenguba/upkpls/gisxr2?name=一缕清风")
"https://www.yuque.com/kenguba/upkpls/gisxr2?name=%E4%B8%80%E7%BC%95%E6%B8%85%E9%A3%8E"
decodeURIComponent("https://www.yuque.com/kenguba/upkpls/gisxr2?name=%E4%B8%80%E7%BC%95%E6%B8%85%E9%A3%8E")

2.解释一下HTTP的超文本传输协议

HTTP 是超文本传输协议,也就是HyperText Transfer Protocol。它可以拆成三个部分:

  • 超文本
  • 传输
  • 协议
    在这里插入图片描述

协议
在这里插入图片描述

生活中的协议,本质上与计算机中的协议是相同的,协议的特点:

  • 协 字,代表的意思是必须有两个以上的参与者。例如三方协议里的参与者有三个:你、公司、学校三个;租房协议里的参与者有两个:你和房东。
  • 议字,代表的意思是对参与者的一种行为约定和规范。例如三方协议里规定试用期期限、毁约金等;租房协议里规定租期期限、每月租金金额、违约如何处理等。针对 HTTP 协议,我们可以这么理解。HTTP是一个用在计算机世界里的协议。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者),以及相关的各种控制和错误处理方式(行为约定和规范)

传输

所谓的「传输」,很好理解,就是把一堆东西从 A 点搬到 B 点,或者从 B 点 搬到 A 点。别轻视了这个简单的动作,它至少包含两项重要的信息。HTTP 协议是一个双向协议。我们在上网冲浪时,浏览器是请求方 A ,百度网站就是应答方 B。双方约定用 HTTP 协议来通信,于是浏览器把请求数据发送给网站,网站再把一些数据返回给浏览器,最后由浏览器渲染在屏幕,就可以看到图片、视频了。
在这里插入图片描述

数据虽然是在 A 和 B 之间传输,但允许中间有中转或接力。就好像第一排的同学想穿递纸条给最后一排的同学,那么传递的过程中就需要经过好多个同学(中间人),这样的传输方式就从「A < - > B」,变成了「A <-> N <-> M <-> B」。而在 HTTP 里,需要中间人遵从 HTTP 协议,只要不打扰基本的数据传输,就可以添加任意额外的东西。针对传输,我们可以进一步理解了 HTTP。HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。

超文本

HTTP 传输的内容是「超文本」 我们先来理解「文本」,在互联网早期的时候只是简单的字符文字,但现在「文本」的涵义已经可以扩展为图片、视频、压缩包等,在 HTTP 眼里这些都算做「文本」。再来理解「超文本」,它就是超越了普通文本的文本,它是文字、图片、视频等的混合体最关键有超链接,能从一个超文本跳转到另外一个超文本。html 就是最常见的超文本了,它本身只是纯文字文件,但内部用很多标签定义了图片、视频等的链接,在经过浏览器的解释,呈现给我们的就是一个文字、有画面的网页了。OK,经过了对 HTTP 里这三个名词的详细解释,就可以给出比「超文本传输协议」这七个字更准确更有技术含量的答案:HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」
在这里插入图片描述

注意: HTTP 不是用于从互联网服务器传输超文本到本地浏览器的协议,也可以是服务器到服务器,所以采用两点之间的描述会更准确

3.HTTP 的特点?HTTP 有哪些缺点?

HTTP 的特点概括

灵活可扩展 主要体现在两个方面。
一个是语义上的自由,只规定了基本格式,比如空格分隔单词,换行分隔字段,其他的各个部分都没有严格的语法限制
另一个是传输形式的多样性,不仅仅可以传输文本,还能传输图片、视频等任意数据,非常方便。
可靠传输 HTTP 基于 TCP/IP,因此把这一特性继承了下来。这属于 TCP 的特性,不具体介绍了。
请求-应答 也就是一发一收、有来有回, 当然这个请求方和应答方不单单指客户端和服务器之间,如果某台服务器作为代理来连接后端的服务端,那么这台服务器也会扮演请求方的角色。
无状态 这里的状态是指通信过程的上下文信息,而每次 http 请求都是独立、无关的,默认不需要保留状态信息

HTTP 缺点

无状态 所谓的优点和缺点还是要分场景来看的,对于 HTTP 而言,最具争议的地方在于它的无状态。
在需要长连接的场景中,需要保存大量的上下文信息,以免传输大量重复的信息,那么这时候无状态就是 http 的缺点了。
但与此同时,另外一些应用仅仅只是为了获取一些数据,不需要保存连接上下文信息,无状态反而减少了网络开销,成为了 http 的优点。
明文传输 即协议里的报文(主要指的是头部)不使用二进制数据,而是文本形式。这当然对于调试提供了便利,但同时也让 HTTP 的报文信息暴露给了外界,给攻击者也提供了便利。WIFI陷阱就是利用 HTTP 明文传输的缺点,诱导你连上热点,然后疯狂抓你所有的流量,从而拿到你的敏感信息。
队头阻塞问题 当 http 开启长连接时,共用一个 TCP 连接,同一时刻只能处理一个请求,那么当前请求耗时过长的情况下,其它的请求只能处于阻塞状态,也就是著名的队头阻塞问题。接下来会有一小节讨论这个问题。

4.HTTP 报文结构是怎样的?

对于 TCP 而言,在传输的时候分为两个部分: **TCP头 **和 数据部分。而 HTTP 类似,也是 header + body 的结构,具体而言:
起始行 + 头部 + 空行 + 实体
由于 http 请求报文和响应报文是有一定区别,因此分开介绍
在这里插入图片描述

起始行

对于请求报文来说,起始行类似下面这样:
GET /home HTTP/1.1
也就是方法 + 路径 + http版本。对于响应报文来说,起始行一般张这个样:
HTTP/1.1 200 OK
响应报文的起始行也叫做状态行。由 http版本、状态码和原因 三部分组成。
在这里插入图片描述

注意:在起始行中,每两个部分之间用空格隔开,最后一个部分后面应该接一个换行,严格遵循 ABNF 语法规范

头部

展示一下请求头和响应头在报文中的位置:
在这里插入图片描述

不管是请求头还是响应头,其中的字段是相当多的,而且牵扯到http非常多的特性,这里就不一一列举的,重点看看这些头部字段的格式:

  • 字段名不区分大小写
  • 字段名不允许出现空格,不可以出现下划线_
  • 字段名后面必须**紧接着 **:

空行

很重要,用来区分开头部和实体。问: 如果说在头部中间故意加一个空行会怎么样?那么空行后的内容全部被视为实体。

实体

就是具体的数据了,也就是 body 部分。请求报文对应请求体, 响应报文对应响应体。
【文章福利】需要C/C++ Linux服务器架构师学习资料及更多面试题加群812855908(资料包括C/C++,Linux,golang技术,内核,nginx,ZeroMQ,mysql,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
在这里插入图片描述

在这里插入图片描述

5.如何理解 HTTP 的请求方法?

http/1.1 规定了以下请求方法(注意,都是大写):

  • GET 通常用来获取资源
  • HEAD 获取资源的元信息
  • POST 提交数据,即上传数据
  • PUT 修改数据
  • DELETE 删除资源(几乎用不到)
  • CONNECT 建立连接隧道,用于代理服务器
  • OPTIONS 列出可对资源实行的请求方法,预检请求,用来跨域请求
  • TRACE 追踪请求-响应的传输路径

6.http 常见字段有哪些?

  • Host
  • Content-Length
  • Connection
  • Content-Encoding
  • Content-Type

7.对于定长和不定长的数据,HTTP 是怎么传输的?

定长包体

对于定长包体而言,发送端在传输的时候一般会带上 Content-Length, 来指明包体的长度。我们用一个nodejs服务器来模拟一下:

const http = require('http');

const server = http.createServer();

server.on('request', (req, res) => {
  if(req.url === '/') {
    res.setHeader('Content-Type', 'text/plain');
    res.setHeader('Content-Length', 10);
    res.write("helloworld");
  }
})

server.listen(8081, () => {
  console.log("成功启动");
})

启动后访问: localhost:8081。浏览器中显示如下:

helloworld

这是长度正确的情况,那不正确的情况是如何处理的呢?我们试着把这个长度设置的小一些:

res.setHeader('Content-Length', 8);

重启服务,再次访问,现在浏览器中内容如下:

hellowor

那后面的ld哪里去了呢?实际上在 http 的响应体中直接被截去了。然后试着将这个长度设置得大一些:

res.setHeader('Content-Length', 12);

此时浏览器显示如下:
在这里插入图片描述

直接无法显示了。可以看到 Content-Length 对于 http 传输过程起到了十分关键的作用,如果设置不当可以直接导致传输失败。

不定长包体

上述是针对于定长包体,那么对于不定长包体而言是如何传输的呢?这里就必须介绍另外一个 http 头部字段了:

Transfer-Encoding: chunked

// Transfer-Encoding: chunked
// Transfer-Encoding: compress
// Transfer-Encoding: deflate
// Transfer-Encoding: gzip
// Transfer-Encoding: identity
// Several values can be listed, separated by a comma
// Transfer-Encoding: gzip, chunked

表示分块传输数据,设置这个字段后会自动产生两个效果:

  • Content-Length 字段会被忽略
  • 基于长连接持续推送动态内容 我们依然以一个实际的例子来模拟分块传输,nodejs 程序如下: const http = require(‘http’);
const server = http.createServer();

server.on('request', (req, res) => {
  if(req.url === '/') {
    res.setHeader('Content-Type', 'text/html; charset=utf8');
    res.setHeader('Content-Length', 10);
    res.setHeader('Transfer-Encoding', 'chunked');
    res.write("<p>来啦</p>");
    setTimeout(() => {
      res.write("第一次传输<br/>");
    }, 1000);
    setTimeout(() => {
      res.write("第二次传输");
      res.end()
    }, 2000);
  }
})

server.listen(8009, () => {
  console.log("成功启动");
})

在这里插入图片描述

用 telnet 抓到的响应如下:
在这里插入图片描述

注意,Connection: keep-alive 及之前的为响应行和响应头,后面的内容为响应体,这两部分用换行符隔开。响应体的结构比较有意思,如下所示:
chunk长度(16进制的数) 第一个chunk的内容 chunk长度(16进制的数) 第二个chunk的内容 … 0
最后是留有有一个空行的,这一点请大家注意。以上便是 http 对于定长数据和不定长数据的传输方式。

8.HTTP 如何处理大文件的传输?

对于几百 M 甚至上 G 的大文件来说,如果要一口气全部传输过来显然是不现实的,会有大量的等待时间,严重影响用户体验。因此,HTTP 针对这一场景,采取了范围请求的解决方案,允许客户端仅仅请求一个资源的一部分。

如何支持

当然,前提是服务器要支持范围请求,要支持这个功能,就必须加上这样一个响应头:

$ curl -I https://www.yuque.com/
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515





$ curl -I http://download.dcloud.net.cn/HBuilder.9.0.2.macosx_64.dmg
$ curl -H  "Range: bytes=0-10" http://download.dcloud.net.cn/HBuilder.9.0.2.macosx_64.dmg -v

//省略
HTTP/1.1 200 OK
...
Accept-Ranges: none

//详细的
HTTP/1.1 200 OK
Server: Tengine
Content-Type: application/octet-stream
Content-Length: 233295878
Connection: keep-alive
Date: Mon, 26 Apr 2021 13:12:46 GMT
x-oss-request-id: 6086BC4E66D721363972F4A8
x-oss-cdn-auth: success
Accept-Ranges: bytes
ETag: "6D932737FD8C6058D6AE93BCC4C74AA7-45"
Last-Modified: Tue, 06 Mar 2018 13:20:31 GMT
x-oss-object-type: Multipart
x-oss-hash-crc64ecma: 7369427768111114923
x-oss-storage-class: Standard
x-oss-server-time: 156
Ali-Swift-Global-Savetime: 1617704046
Via: cache15.l2cn1809[0,200-0,H], cache2.l2cn1809[1,0], cache7.cn682[39,39,200-0,M], cache2.cn682[44,0]
Age: 778
X-Cache: MISS TCP_MISS dirn:-2:-2
X-Swift-SaveTime: Mon, 26 Apr 2021 13:25:44 GMT
X-Swift-CacheTime: 3600
Timing-Allow-Origin: *
EagleId: af062a4216194435440612604e

假如在响应中存在Accept-Ranges首部(并且它的值不为 “none”),那么表示该服务器支持范围请求 在上面的响应中,Accept-Ranges: bytes 表示界定范围的单位是 bytes 。这里 Content-Length也是有效信息,因为它提供了要检索的图片的完整大小
如果站点未发送Accept-Ranges首部,那么它们有可能不支持范围请求。一些站点会明确将其值设置为 “none”,以此来表明不支持。在这种情况下,某些应用的下载管理器会将暂停按钮禁用。

curl -I https://www.youtube.com/watch?v=EwTZ2xpQwpA

HTTP/1.1 200 OK
...
Accept-Ranges: none

Range 字段拆解

而对于客户端而言,它需要指定请求哪一部分,通过 Range 这个请求头字段确定,格式为bytes=x-y。接下来就来讨论一下这个 Range 的书写格式:
0-499 表示从开始到第 499 个字节。
500- 表示从第 500 字节到文件终点。
-100 表示文件的最后100个字节。
服务器收到请求之后,首先验证范围是否合法,如果越界了那么返回416错误码,否则读取相应片段,返回206状态码。同时,服务器需要添加 Content-Range 字段,这个字段的格式根据请求头中Range字段的不同而有所差异。具体来说,请求单段数据和请求多段数据,响应头是不一样的。举个例子:

// 单段数据
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"
Range: bytes=0-9

// 多段数据
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"
Range: bytes=0-9, 30-39

接下来就分别来讨论着两种情况

单段数据

对于单段数据的请求,返回的响应如下:

HTTP/1.1 206 Partial Content
Content-Length: 10
Accept-Ranges: bytes
Content-Range: bytes 0-9/100

i am xxxxx

值得注意的是Content-Range字段,0-9表示请求的返回,100表示资源的总大小,很好理解。

多段数据

接下来看看多段请求的情况。得到的响应会是下面这个形式:

HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=00000010101
Content-Length: 189
Connection: keep-alive
Accept-Ranges: bytes


--00000010101
Content-Type: text/plain
Content-Range: bytes 0-9/96

i am xxxxx
--00000010101
Content-Type: text/plain
Content-Range: bytes 20-29/96

eex jspy e
--00000010101--

这个时候出现了一个非常关键的字段Content-Type: multipart/byteranges;boundary=00000010101,它代表了信息量是这样的:
请求一定是多段数据请求
响应体中的分隔符是 00000010101
因此,在响应体中各段数据之间会由这里指定的分隔符分开,而且在最后的分隔末尾添上–表示结束。以上就是 http 针对大文件传输所采用的手段。
与分块传输编码的对比
Transfer-Encoding 首部允许分块编码,这在数据量很大,并且在请求未能完全处理完成之前无法知晓响应的体积大小的情况下非常有用。服务器会直接把数据发送给客户端而无需进行缓冲或确定响应的精确大小——后者会增加延迟。范围请求与分块传输是兼容的,可以单独或搭配使用

9.HTTP 中如何处理表单数据的提交?

在 http 中,有两种主要的表单提交的方式,体现在两种不同的Content-Type取值:

  • application/x-www-form-urlencoded
  • multipart/form-data 由于表单提交一般是POST请求,很少考虑GET,因此这里我们将默认提交的数据放在请求体中

application/x-www-form-urlencoded

对于application/x-www-form-urlencoded格式的表单内容,有以下特点:

  • 其中的数据会被编码成以&分隔的键值对
  • 字符以URL编码方式编码。如:
// 转换过程: {a: 1, b: 2} -> a=1&b=2 -> 如下(最终形式) "
a%3D1%26b%3D2"

multipart/form-data

对于multipart/form-data而言:
请求头中的Content-Type字段会包含boundary,且boundary的值有浏览器默认指定。例:

Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe

数据会分为多个部分,每两个部分之间通过分隔符来分隔,每部分表述均有 HTTP 头部描述子包体,如Content-Type,在最后的分隔符会加上–表示结束。
相应的请求体是下面这样:

Content-Disposition: form-data;name="data1";
Content-Type: text/plain
data1
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition: form-data;name="data2";
Content-Type: text/plain
data2
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--

值得一提的是,multipart/form-data 格式最大的特点在于:每一个表单元素都是独立的资源表述。另外,你可能在写业务的过程中,并没有注意到其中还有boundary的存在,如果你打开抓包工具,确实可以看到不同的表单元素被拆分开了,之所以在平时感觉不到,是以为浏览器和 HTTP 给你封装了这一系列操作。而且,在实际的场景中,对于图片等文件的上传,基本采用multipart/form-data而不用application/x-www-form-urlencoded,因为没有必要做 URL 编码,带来巨大耗时的同时也占用了更多的空间。

10.如何理解 HTTP 代理?

我们知道在 HTTP 是基于请求-响应模型的协议,一般由客户端发请求,服务器来进行响应。当然,也有特殊情况,就是代理服务器的情况。引入代理之后,作为代理的服务器相当于一个中间人的角色,对于客户端而言,表现为服务器进行响应;而对于源服务器,表现为客户端发起请求,具有双重身份。那代理服务器到底是用来做什么的呢?

功能

  • 负载均衡 客户端的请求只会先到达代理服务器,后面到底有多少源服务器,IP都是多少,客户端是不知道的。因此,这个代理服务器可以拿到这个请求之后,可以通过特定的算法分发给不同的源服务器,让各台源服务器的负载尽量平均。当然,这样的算法有很多,包括随机算法、轮询、一致性hash、LRU(最近最少使用)等等,不过这些算法并不是本文的重点,大家有兴趣自己可以研究一下。
  • 保障安全 利用心跳机制监控后台的服务器,一旦发现故障机就将其踢出集群。并且对于上下行的数据进行过滤,对非法 IP限流,这些都是代理服务器的工作。
  • 缓存代理 将内容缓存到代理服务器,使得客户端可以直接从代理服务器获得而不用到源服务器那里 相关头部字段

Via

代理服务器需要标明自己的身份,在 HTTP 传输中留下自己的痕迹,怎么办呢?通过Via字段来记录。举个例子,现在中间有两台代理服务器,在客户端发送请求后会经历这样一个过程:
客户端 -> 代理1 -> 代理2 -> 源服务器
在源服务器收到请求后,会在请求头拿到这个字段:
Via: proxy_server1, proxy_server2
而源服务器响应时,最终在客户端会拿到这样的响应头:
Via: proxy_server2, proxy_server1
可以看到,Via中代理的顺序即为在 HTTP 传输中报文传达的顺序

X-Forwarded-For

字面意思就是为谁转发, 它记录的是请求方的IP地址(注意,和Via区分开,X-Forwarded-For记录的是请求方这一个IP)。

X-Real-IP

是一种获取用户真实 IP 的字段,不管中间经过多少代理,这个字段始终记录最初的客户端的IP。相应的,还有X-Forwarded-Host和X-Forwarded-Proto,分别记录客户端(注意哦,不包括代理)的域名和协议名。

X-Forwarded-For产生的问题

前面可以看到,X-Forwarded-For这个字段记录的是请求方的 IP,这意味着每经过一个不同的代理,这个字段的名字都要变,从客户端到代理1,这个字段是客户端的 IP,从代理1到代理2,这个字段就变为了代理1的 IP。但是这会产生两个问题:

  • 意味着代理必须解析 HTTP 请求头,然后修改,比直接转发数据性能下降。
  • 在 HTTPS 通信加密的过程中,原始报文是不允许修改的。 由此产生了代理协议,一般使用明文版本,只需要在 HTTP请求行上面加上这样格式的文本即可:
// PROXY + TCP4/TCP6 + 请求方地址 + 接收方地址 + 请求端口 + 接收端口
PROXY TCP4 0.0.0.1 0.0.0.2 1111 2222
GET / HTTP/1.1

这样就可以解决X-Forwarded-For带来的问题了

11.说说 HTTP1.1 相比 HTTP1.0 提高了什么性能?

HTTP1.1 相比 HTTP1.0 性能上的改进:

  • 使用 TCP 长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
  • 支持 管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。

但 HTTP1.1 还是有性能瓶颈:

  • 请求/响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩 Body 的部分

  • 发送冗长的首部。每次互相发送相同的首部造成的浪费较多

  • 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;

  • 没有请求优先级控制

  • 请求只能从客户端开始,服务器只能被动响应

12.那上面的 HTTP1.1 的性能瓶颈,HTTP2 做了什么优化?

HTTP/2是Web的未来,demo演示!HTTP2 协议是 基于 HTTPS 的,所以 HTTP2 的安全性也是有保障的。那 HTTP2 相比 HTTP1.1 性能上的改进:

1. 头部压缩

HTTP2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的分。这就是所谓的 HPACK 算法

  • 索引表
  • 霍夫曼编码在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

2. 二进制格式

HTTP2 不再像 HTTP1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。
在这里插入图片描述

这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率 3. 数据流 HTTP2 的数据包不是按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。每个请求或回应的所有数据包,称为一个数据流(Stream)。每个数据流都标记着一个独一无二的编号,其中规定客户端发出的数据流编号为奇数, 服务器发出的数据流编号为偶数 客户端还可以指定数据流的优先级。优先级高的请求,服务器就先响应该请求。
在这里插入图片描述

  • 同域名下所有通信都在单个连接上完成。
  • 单个连接可以承载任意数量的双向数据流。
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

这一特性,使性能有了极大提升:

  • 同个域名只需要占用一个 TCP 连接,消除了因多个 TCP 连接而带来的延时和内存消耗。
  • 单个连接上可以并行交错的请求和响应,之间互不干扰。
  • 在HTTP2中,每个请求都可以带一个 31bit的优先值,0表示最高优先级,数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

多路复用 HTTP2 是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。移除了 HTTP1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,大幅度提高了连接的利用率。举例来说,在一个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。
在这里插入图片描述

服务器推送 HTTP2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会用到的 JS、CSS 文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫 Cache Push)

13.HTTP2 有哪些缺陷?HTTP3 做了哪些优化?

HTTP2 主要的问题在于,多个 HTTP 请求在复用一个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。所以一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。
HTTP1.1 中的管道(pipeline) 传输中如果有一个请求阻塞了,那么队列后请求也统统被阻塞住了
HTTP2 多请求复用一个TCP连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。
这都是基于 TCP 传输层的问题,所以 HTTP3 把 HTTP 下层的 TCP 协议改成了 UDP!UDP 发生是不管顺序,也不管丢包的,所以不会出现 HTTP1.1 的队头阻塞 和 HTTP2 的一个丢包全部重传问题
在这里插入图片描述

大家都知道 UDP 是不可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。
QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响。
TL3 升级成了最新的1.3版本,头部压缩算法也升级成了 QPack
HTTPS 要建立一个连接,要花费 6 次交互,先是建立三次握手,然后是 TLS/1.3 的三次握手。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互 合并成了 3 次,减少了交互次数
在这里插入图片描述

所以, QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP2 的多路复用的协议。QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题。所以 HTTP3 现在普及的进度非常的缓慢,不知道未来 UDP 是否能够逆袭 TCP

14.HTTP 与 HTTPS 有哪些区别?

  • HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
  • HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP
    三次握手之后,还需进行SSL/TLS 的握手过程,才可进入加密报文传输。
  • HTTP 的端口号是 80,HTTPS 的端口号是 443。
  • HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的

15.HTTPS 解决了 HTTP 的哪些问题?

HTTP 由于是明文传输,所以安全上存在以下三个风险:

  • 窃听风险,比如通信链路上可以获取通信内容,用户号容易没。
  • 篡改风险,比如强制入垃圾广告,视觉污染,用户眼容易瞎。
  • 冒充风险,比如冒充淘宝网站,用户钱容易没。

在这里插入图片描述

HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议,可以很好的解决了上述的风险:

  • 信息加密:交互信息无法被窃取
  • 校验机制:无法篡改通信内容,篡改了就不能正常显示
  • 身份证书:证明淘宝是真的淘宝网 可见,只要自身不做「恶」,SSL/TLS 协议是能保证通信是安全的

16.HTTPS 是如何解决上面的三个风险的?

混合加密的方式实现信息的机密性,解决了窃听的风险。

  • 摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
  • 将服务器公钥放入到数字证书中,解决了冒充的风险

混合加密

通过混合加密的方式可以保证信息的机密性,解决了窃听的风险。
在这里插入图片描述

混合加密 HTTPS 采用的是对称加密和非对称加密结合的「混合加密」方式:

  • 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
  • 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。 采用「混合加密」的方式的原因:
  • 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

摘要算法

摘要算法用来实现完整性,能够为数据生成独一无二的「指纹」,用于校验数据的完整性,解决了篡改的风险
在这里插入图片描述

客户端在发送明文之前会通过摘要算法算出明文的「指纹」,发送的时候把「指纹 + 明文」一同 加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的「指纹」和当前算出的「指纹」做比较,若「指纹」相同,说明数据是完整的。

数字证书

客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。这就存在些问题,如何保证公钥不被篡改和信任度?所以这里就需要借助第三方权威机构 CA(数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。
在这里插入图片描述

通过数字证书的方式保证服务器公钥的身份,解决冒充的风险

17.HTTPS 是如何建立连接的?其间交互了什么?

SSL/TLS 协议基本流程:
1.TCP 三次同步握手
2.客户端向服务器索要并验证服务器的公钥
3.双方协商生产「会话秘钥」
4.SSL 安全加密隧道协商完成
5.双方采用「会话秘钥」进行加密通信。
2,3步是 SSL/TLS 的建立过程,也就是握手阶段 SSL/TLS 的握手阶段涉及四次通信,可见下图:
在这里插入图片描述

SSL/TLS 协议建立的详细流程:

  1. ClientHello
    首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息:(1)客户端支持的 SSL/TLS 协议版本,如 TLS 1.2 版本。(2)客户端生产的随机数(Client Random),后面用于生产「会话秘钥」。(3)客户端支持的密码套件列表,如 RSA 加密算法。
  2. SeverHello
    服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:(1)

    以上是关于2021最常见的网络原理面试题好文收藏的主要内容,如果未能解决你的问题,请参考以下文章

    2021年10月份大厂网络工程师面试笔试题题推荐收藏

    2021年Javascript最常见的面试题以及答案(持续更新中...)

    建议收藏复盘:2021年最新最全最实用的Android岗学习资料/面试真题

    Java大数据工程师最常见的25道面试题,建议收藏

    前端面试题2021(超详细)

    前端面试题2021(超详细)