2024 http http2.0 TCP UDP 面试题学习笔记

171 阅读24分钟

0 网络OSI七层模型,HTTP / TCP / IP

1 http

一个HTTP请求报文由请求行(request line)、请求头(header)、请求体 组成

1.1 http 常见请求/响应头及其含义

通用头(请求头和响应头都有的首部)

字段作用
Cache-Control控制缓存public:表示响应可以被任何对象缓存(包括客户端/代理服务器) private(默认值):响应只能被单个客户缓存,不能被代理服务器缓存 no-cache:缓存要经过服务器验证,在浏览器使用缓存前,会对比ETag,若没变则返回304,使用缓存 no-store:禁止任何缓存
Connection是否需要持久连接(HTTP 1.1默认持久连接)keep-alive / close
Transfer-Encoding报文主体的传输编码格式chunked(分块) / identity(未压缩和修改) / gzip(LZ77压缩) / compress(LZW压缩,弃用) / deflate(zlib结构压缩)

请求头

字段作用语法
Accept告知(服务器)客户端可以处理的内容类型text/html、image//*
If-Modified-Since将 Last-Modified 的值发送给服务器,询问资源是否已经过期(被修改),过期则返回新资源,否则返回304示例:If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
If-Unmodified-Since将Last-Modified的值发送给服务器,询问文件是否被修改,若没有则返回200,否则返回412预处理错误,可用于断点续传。通俗点说 If-Unmodified-Since 是文件没有修改时下载,If-Modified-Since 是文件修改时下载示例:If-Unmodified-Since: Wed, 21 Oct 2015 07:28:00 GMT
If-None-Match将 ETag 的值发送给服务器,询问资源是否已经过期(被修改),过期则返回新资源,否则返回304示例:If-None-Match: "bfc13a6472992d82d"
If-Match将 ETag 的值发送给服务器,询问文件是否被修改,若没有则返回200,否则返回412预处理错误,可用于断点续传示例:If-Match: "bfc129c88ca92d82d"
Range告知服务器返回文件的哪一部分, 用于断点续传示例:Range: bytes=200-1000, 2000-6576, 19000-
Host指明了服务器的域名(对于虚拟主机来说),以及(可选的)服务器监听的TCP端口号示例:Host:www.baidu.com
User-Agent告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本User-Agent: Mozilla/ () ()

响应头

字段作用语法
Location需要将页面重新定向至的地址。一般在响应码为3xx的响应中才会有意义Location:
ETag资源的特定版本的标识符,如果内容没有改变,Web服务器不需要发送完整的响应ETag: "<etag_value>"
Server处理请求的源头服务器所用到的软件相关信息Server:

实体头(针对请求报文和响应报文的实体部分使用首部)

字段作用语法
Allow资源可支持 http 请求的方法Allow: ,示例:Allow: GET, POST, HEAD
Last-Modified资源最后的修改时间,用作一个验证器来判断接收到的或者存储的资源是否彼此一致,精度不如ETag示例:Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
Expires响应过期时间Expires: ,示例:Expires: Wed, 21 Oct 2020 07:28:00 GMT

1.2 HTTP/1.0 和 HTTP/1.1 有什么区别

  • 长连接: HTTP/1.1 connection 支持长连接和请求的流水线,在一个 TCP 连接上可以传送多个HTTP请求,避免了因为多次建立TCP连接的时间消耗和延时
  • 缓存处理: HTTP/1.1 引入Entity tag,If-Unmodified-Since, If-Match, If-None-Match等新的请求头来控制缓存
  • 带宽优化及网络连接的使用: HTTP1.1 则在请求头引入了 range 头域,支持断点续传功能
  • Host 头处理: 在HTTP/1.0中认为每台服务器都有唯一的IP地址,但随着虚拟主机技术的发展,多个主机共享一个IP地址愈发普遍,HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会400错误

1.3 介绍一下 HTTP/2.0 新特性

  • 二进制分帧传输: HTTP/2 采用二进制格式传输数据,相比于HTTP/1.1的文本格式,二进制格式具有更好的解析性和拓展性
  • 多路复用: 即多个请求都通过一个TCP连接并发地完成
  • 服务端推送: 服务端能够主动把资源推送给客户端
  • header压缩: HTTP/2压缩消息头,减少了传输数据的大小

1.4 HTTP/2.0 解决的问题、多路复用原理

HTTP/1.1 存在的问题:

  • TCP慢启动: TCP连接建立后,会经历一个先慢后快的发送过程,就像汽车启动一般,如果我们的网页文件(HTML/JS/CSS/icon)都经过一次慢启动,对性能是不小的损耗。另外慢启动是TCP为了减少网络拥塞的一种策略,我们是没有办法改变的。
  • 多条TCP连接竞争带宽: 如果同时建立多条TCP连接,当带宽不足时就会竞争带宽,影响关键资源的下载。
  • HTTP/1.1 队头阻塞: 尽管 HTTP/1.1 长链接可以通过一个 TCP 连接传输多个请求,但同一时刻只能处理一个请求,当前请求未结束前,其他请求只能处于阻塞状态。

为了解决 http1.1 的问题,HTTP/2 一个域名只使用 一个 TCP ⻓连接来传输数据,而且请求直接是并行的、非阻塞的,这就是多路复用

实现原理: HTTP/2 引入了一个二进制分帧层,客户端和服务端进行传输时,数据会先经过二进制分帧层处理,转化为一个个带有请求ID的帧,这些帧在传输完成后根据ID组合成对应的数据。

1.5 HTTP/3.0

尽管 HTTP/2 解决了很多 1.1 的问题,但HTTP/2仍然存在一些缺陷,这些缺陷并不是来自于HTTP/2协议本身,而是来源于底层的TCP协议,我们知道TCP链接是可靠的连接,如果出现了丢包,那么整个连接都要等待重传,HTTP/1.1 可以同时使用6个TCP连接,一个阻塞另外五个还能工作,但 HTTP/2 只有一个TCP连接,阻塞的问题便被放大了。

由于TCP协议已经被广泛使用,我们很难直接修改TCP协议,基于此,HTTP/3选择了一个折衷的方法—— HTTP/2 在 UDP 的基础上实现多路复用、0-RTT、TLS加密、流量控制、丢包重传等功能。

0-RTT

通过使用类似 TCP 快速打开的技术,缓存当前会话的上下文,在下次恢复会话的时候,只需要将之前的缓存传递给服务端验证通过就可以进行传输了。

纠错机制

假如这次我要发送三个包,那么协议会算出这三个包的异或值并单独发出一个校验包,也就是总共发出了四个包。

当出现其中的非校验包丢包的情况时,可以通过另外三个包计算出丢失的数据包的内容。

当然这种技术只能使用在丢失一个包的情况下,如果出现丢失多个包就不能使用纠错机制了,只能使用重传的方式了。

1.6 HTTP 和 HTTPS 有何区别

  • HTTP 使用 80 端口,而 HTTPS 使用 443 端口
  • HTTPS 需要申请域名证书
  • HTTP是超文本传输协议,是明文传输;HTTPS是经过SSL加密的协议,传输更安全
  • HTTPS 比 HTTP 慢,因为HTTPS除了 TCP握手的三个包,还要加上 SSL握手的包

1.7 https 如何验证公钥没有被篡改呢?

  1. 首先浏览器读取证书中的证书所有者、有效期等信息进行一一验证
  2. 浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器来的证书的颁发者CA比对,用于校验证书是否为合法机构颁发
  3. 如果找不到,浏览器会报错,说明服务器发来的证书是不可信任的;如果找到,浏览器就会从操作系统中取出颁发者CA的公钥,然后对服务器发来的证书里面的签名进行解密
  4. 浏览器使用相同的 hash 算法根据证书内容计算出摘要信息,将这个计算的值与证书解密的值进行比对
  5. 对比结果一致,则说明服务器发来的证书合法

1.8 SSL / TLS

SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。SSL通过 互相认证 、使用 数字签名 确保完整性使用 加密 确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和 SSL握手协议。

TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。

SSL是Netscape开发的专门用户保护Web通讯的,目前版本为3.0。最新版本的TLS 1.0是IETF(工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。两者差别极小,可以理解为SSL 3.1。

HTTPS 还是通过了 HTTP 来传输信息,但是信息通过 TLS 协议进行了加密。

TLS 协议位于应用层之下, 传输层之上。首次进行 TLS 协议传输需要两个 RTT ,接下来可以通过 Session Resumption 减少到一个 RTT。 (RTT : Round-Trip Time 往返时延)

在 TLS 中使用了两种加密技术,分别为:对称加密和非对称加密。

对称加密

对称加密就是两边拥有相同的秘钥,两边都知道如何将密文加密解密。

这种加密方式固然很好,但是问题就在于如何让双方知道秘钥。因为传输数据都是走的网络,如果将秘钥通过网络的方式传递的话,一旦秘钥被截获就没有加密的意义的。

非对称加密

有公钥私钥之分,公钥所有人都可以知道,可以将数据用公钥加密,但是将数据解密必须使用私钥解密,私钥只有分发公钥的一方才知道。

这种加密方式就可以完美解决对称加密存在的问题。假设现在两端需要使用对称加密,那么在这之前,可以先使用非对称加密交换秘钥。

简单流程:首先服务端将公钥公布出去,那么客户端也就知道公钥了。接下来客户端创建一个秘钥,然后通过公钥加密并发送给服务端,服务端接收到密文以后通过私钥解密出正确的秘钥,这时候两端就都知道秘钥是什么了。

TLS 握手过程如下图:

1 客户端发送一个随机值以及需要的协议和加密方式。

2 服务端收到客户端的随机值,自己也产生一个随机值,并根据客户端需求的协议和加密方式来加密随机值,并且发送自己的证书。

3 客户端收到服务端的证书并验证是否有效,验证通过会再生成一个随机值,通过服务端证书的公钥去加密这个随机值并发送给服务端。

4 服务端收到加密过的随机值并使用私钥解密获得第三个随机值,这时候两端都拥有了三个随机值,可以通过这三个随机值按照之前约定的加密方式生成密钥,接下来的通信就可以通过该密钥来加密和解密。

通过以上步骤,在 TLS 握手阶段,两端使用非对称加密的方式来通信,但是因为非对称加密损耗的性能比对称加密大,所以在正式传输数据时,两端使用对称加密的方式通信。

2 TCP

常考面试题:UDP 与 TCP 的区别是什么?

TCP 基本是和 UDP 反着来,建立连接断开连接都需要先需要进行握手。在传输数据的过程中,通过各种算法保证数据的可靠性,当然带来的问题就是相比 UDP 来说不那么的高效。

2.1 三次握手

首先假设主动发起请求的一端称为客户端,被动连接的一端称为服务端。不管是客户端还是服务端,TCP 连接建立完后都能发送和接收数据,所以 TCP 是一个 全双工 的协议

起初两端都为 CLOSED 状态。在通信开始前,双方都会创建 TCB。 服务器创建完 TCB 后便进入 LISTEN 状态,此时开始等待客户端发送数据。

第一次握手

客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。

第二次握手

服务端收到连接请求报文段后,如果同意连接,则会发送一个应答 SYN-ACK,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。

第三次握手

当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。

PS:第三次握手中可以包含数据,通过快速打开(TFO)技术就可以实现这一功能。其实只要涉及到握手的协议,都可以使用类似 TFO 的方式,客户端和服务端存储相同的 cookie,下次握手时发出 cookie 达到减少 RTT 的目的。

明明两次就可以建立起连接,为什么 TCP 建立连接需要三次握手 ?

因为这是为了防止出现失效的连接请求报文段被服务端接收的情况,服务端空等链接请求,从而产生服务端资源的浪费

客户端发送了一个连接请求 A,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求,然后接收数据后释放了连接。

假设这时候连接请求 A 在两端关闭后终于抵达了服务端,那么此时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入等待接收状态。但是客户端其实是 CLOSED 的状态,那么就会导致服务端一直等待,造成资源的浪费。

PS:在建立连接中,任意一端掉线,TCP 都会重发 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYN Flood 攻击。遇到这种情况可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求。

Syn-Flood攻击是当前网络上最为常见的DDoS攻击,也是最为经典的拒绝服务攻击,它利用了TCP协议实现上的一个缺陷,通过向网络服务所在端口发送大量的伪造源地址的攻击报文,就可能造成目标服务器中的半开连接队列被占满,从而阻止其他正常的用户进行访问。

2.2 四次挥手

TCP 是全双工的,在断开连接时两端都需要发送 FIN 和 ACK。

第一次握手

若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

第二次握手

B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。

第三次握手

B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。

PS:通过延迟确认的技术(通常有时间限制,否则对方会误认为需要重传),可以将第二次和第三次握手合并,延迟 ACK 包的发送。

第四次握手

A 收到释放请求后,向 B 发送确认 ACK 应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

为什么A要进入TIME-WAIT状态,等待 2MSL 时间后才进入 CLOSED 状态?

为了保证 B 能收到 A 的确认应答。若 A 发完确认应答后直接进入 CLOSED 状态,如果确认应答因为网络问题一直没有到达,那么会造成 B 不能正常关闭。

2.3 超时重传机制 ARQ

通过确认和超时机制保证了数据的正确送达,ARQ 协议包含停止等待 ARQ 和连续 ARQ 两种协议。

2.3.1 正常传输过程

只要 A 向 B 发送一段报文,都要停止发送并启动一个定时器,等待对端回应,在定时器时间内接收到对端应答就取消定时器并发送下一段报文。

2.3.1 发送报文丢失或出错

在报文传输的过程中可能会出现丢包。这时候超过定时器设定的时间就会再次发送丢失的数据直到对端响应,所以需要每次都备份发送的数据

即使报文正常的传输到对端,也可能出现在传输过程中报文出错的问题。这时候对端会抛弃该报文并等待 A 端重传。

PS:一般定时器设定的时间都会大于一个 RTT 的平均时间。

2.3.1 确认 ACK 超时或丢失

对端传输的应答也可能出现丢失或超时的情况。那么超过定时器时间 A 端照样会重传报文。这时候 B 端收到相同序号的报文会丢弃该报文并重传应答,直到 A 端发送下一个序号的报文。

在超时的情况下也可能出现应答很迟到达,这时 A 端会判断该序号是否已经接收过,如果接收过只需要丢弃应答即可。

缺点 : 假设在良好的网络环境中,每次发送数据都需要等待片刻肯定是不能接受的,所以就有了连续 ARQ。

2.3.2 连续 ARQ

在连续 ARQ 中,发送端拥有一个发送窗口,可以在没有收到应答的情况下持续发送窗口内的数据,这样相比停止等待 ARQ 协议来说减少了等待时间,提高了效率。

2.3.2 累计确认

连续 ARQ 中,接收端会持续不断收到报文。如果和停止等待 ARQ 中接收一个报文就发送一个应答一样,就太浪费资源了。通过累计确认,可以在收到多个报文以后统一回复一个应答报文。报文中的 ACK 标志位可以用来告诉发送端这个序号之前的数据已经全部接收到了,下次请发送这个序号后的数据。

但是累计确认也有一个弊端。在连续接收报文时,可能会遇到接收到序号 5 的报文后,并未接收到序号 6 的报文,然而序号 7 以后的报文已经接收。遇到这种情况时,ACK 只能回复 6,这样就会造成发送端重复发送数据的情况。

2.4 滑动窗口 - 流量控制

在 TCP 中,两端其实都维护着窗口:分别为发送端窗口和接收端窗口。

发送端窗口是由接收窗口剩余大小决定的。接收方会把当前接收窗口的剩余大小写入应答报文,发送端收到应答后根据该值和当前网络拥塞情况设置发送窗口的大小,所以发送窗口的大小是不断变化的。

滑动窗口 帮助 TCP 实现了流量控制的功能。接收方通过报文告知发送方还可以发送多少数据,从而保证接收方能够来得及接收数据,防止出现接收方带宽已满,但是发送方还一直发送数据的情况。

2.4.1 Zero 窗口

在发送报文的过程中,可能会遇到对端出现零窗口的情况。在该情况下,发送端会停止发送数据,并启动 persistent timer 。该定时器会定时发送请求给对端,让对端告知窗口大小。在重试次数超过一定次数后,可能会中断 TCP 链接。

2.5 拥塞处理

拥塞处理:作用于网络,防止过多的数据拥塞网络,避免出现网络负载过大的情况。

流量控制:作用于接收方,保证接收方来得及接受数据。

拥塞处理包括了四个算法,分别为:慢开始,拥塞避免,快速重传,快速恢复。

2.5.1 慢开始算法

慢开始算法,顾名思义,就是在传输开始时将发送窗口慢慢指数级扩大,从而避免一开始就传输大量数据导致网络拥塞。比如下载资源时,每当我们开始下载的时候都会发现下载速度是慢慢提升的,而不是一蹴而就直接拉满带宽。

慢开始算法步骤具体如下

  1. 连接初始设置拥塞窗口(Congestion Window) 为 1 MSS(一个分段的最大数据量)
  2. 每过一个 RTT 就将窗口大小乘二
  3. 指数级增长肯定不能没有限制的,所以有一个阈值限制,当窗口大小大于阈值时就会启动拥塞避免算法。

2.5.2 拥塞避免算法

拥塞避免算法相比简单点,每过一个 RTT 窗口大小只加一,这样能够避免指数级增长导致网络拥塞,慢慢将大小调整到最佳值。

在传输过程中可能定时器超时的情况,这时候 TCP 会认为网络拥塞了,会马上进行以下步骤:

  • 将阈值设为当前拥塞窗口的一半
  • 将拥塞窗口设为 1 MSS
  • 启动拥塞避免算法

2.5.3 快速重传 - 快恢复

快速重传 一般和 快恢复一起出现。一旦接收端收到的报文出现失序的情况,接收端只会回复最后一个顺序正确的报文序号。如果发送端收到三个重复的 ACK,无需等待定时器超时而是直接启动快速重传算法。具体算法分为两种:

TCP Taho 实现如下

  • 将阈值设为当前拥塞窗口的一半
  • 将拥塞窗口设为 1 MSS
  • 重新开始慢开始算法

TCP Reno 实现如下

  • 拥塞窗口减半
  • 将阈值设为当前拥塞窗口
  • 进入快恢复阶段(重发对端需要的包,一旦收到一个新的 ACK 答复就退出该阶段),这种方式在丢失多个包的情况下就不那么好了
  • 使用拥塞避免算法

2.5.4 TCP New Ren 改进后的快恢复

TCP New Reno 算法改进了之前 TCP Reno 算法的缺陷。在之前,快恢复中只要收到一个新的 ACK 包,就会退出快恢复。

TCP New Reno 中,TCP 发送方先记下三个重复 ACK 的分段的最大序号。

假如我有一个分段数据是 1 ~ 10 这十个序号的报文,其中丢失了序号为 3 和 7 的报文,那么该分段的最大序号就是 10。发送端只会收到 ACK 序号为 3 的应答。这时候重发序号为 3 的报文,接收方顺利接收的话就会发送 ACK 序号为 7 的应答。这时候 TCP 知道对端是有多个包未收到,会继续发送序号为 7 的报文,接收方顺利接收并会发送 ACK 序号为 11 的应答,这时发送端认为这个分段接收端已经顺利接收,接下来会退出快恢复阶段。

3 UDP

UDP 与 TCP 的区别是什么?

首先 UDP 协议是面向无连接的,也就是说不需要在正式传递数据之前先连接起双方。然后 UDP 协议只是数据报文的搬运工,不保证有序且不丢失的传递到对端,并且UDP 协议也没有任何控制流量的算法,总的来说 UDP 相较于 TCP 更加的轻便。

3.1 面向无连接

首先 UDP 是不需要和 TCP 一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。

并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。

具体来说就是:

  • 在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是 UDP 协议,然后就传递给网络层了
  • 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作

3.2 不可靠性

首先不可靠性体现在无连接,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。

并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。

再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。

3.3 高效

虽然 UDP 协议不是那么的可靠,但是正是因为它不是那么的可靠,所以也就没有 TCP 那么复杂了,需要保证数据不丢失且有序到达。

因此 ****UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的。

UDP 头部包含了以下几个数据

  • 两个十六位的端口号,分别为源端口(可选字段)和目标端口
  • 整个数据报文的长度
  • 整个数据报文的检验和(IPv4 可选 字段),该字段用于发现头部信息和数据中的错误

3.4 传输方式

UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式

3.5 适合使用的场景

直播、会议对数据传输要求高的场景