更多特训营笔记详见个人主页【面试鸭特训营】专栏
250113
1. 说说 TCP 的四次挥手
四次挥手
- 第 1 次:客户端 → 服务端,发送 FIN 包(FIN = 1,表示要关闭连接)。
- 客户端表达了想和服务端断开连接的意愿。
- 客户端进入 FIN_WAIT_1 状态。
- 服务端接受到 FIN 后,不再接收数据,但仍可能继续发送数据。
- 第 2 次:服务端 → 客户端,发送 ACK 包(ACK = 1,表示确认收到客户端的请求)。
- 服务端收到了客户端的意愿。
- 服务端进入 CLOSE_WAIT 状态。
- 客户端今日 FIN_WAIT_2 状态。
- 第 3 次:服务端 → 客户端,发送 FIN 包。
- 服务端将所有数据发送给客户端。
- 服务端进入 LAST_ACK 状态。
- 客户端手动 FIN 后,准备关闭连接。
- 第 4 次:客户端 → 服务端,发送 ACK 包(ACK = 1,表示确认收到服务端的请求)。
- 客户端收到了服务端的意愿。
- 客户端进入 TIME_WAIT 状态,等待可能延迟的 FIN 包。
- 服务端收到 ACK 后,关闭连接,进入 CLOSE 状态。
- 客户端在 TIME_WAIT 计时结束后(2MSL),正式关闭连接。
为什么一定是四次
- TCP 在断开连接时,客户端和服务端都需要关闭连接,才能保证数据不丢失。
- 每一次关闭连接都是
一次 FIN(我发完了)
和一次 ACK(我收到了)
。 - 客户端和服务端各一次 FIN + ACK ,总共是四次通信。
什么情况下可以只有三次挥手
- 客户端给服务端发送 FIN 包后,服务端收到 FIN 包时【没有数据要发送给客户端】。
- 这时候服务端会把 FIN 和 ACK 一起发给客户端(第 2 次和第 3 次挥手合并了)。
- 这种情况下只有三次挥手。
2. 说说TCP 的粘包和拆包
-
粘包和拆包现象通常出现在基于TCP协议的网络通信中。
-
由于TCP是面向字节流的协议,发送方和接收方的数据在传输过程中是以字节流的方式进行传输的,数据的边界并不是由TCP协议本身来界定的。
粘包
- 造成原因
- 由于 TCP 缓冲区大小的限制,多个小的数据包被合并成一个大的数据包进行发送,接收方需要拆除完整的数据包。
拆包
- 造成原因
- 由于 TCP 缓冲区大小的限制,一个大的数据包被拆分成多个小的数据包包进行发送,接收方需要识别并重组这些分散的数据。
解决方案
- 固定长度协议
- 发送方将每个数据包的长度固定,接收方每次读取固定长度的数据。
- 简单方便,但不易于拓展,且由于需要填充空格会导致浪费空间。
- 适合场景:传输内容长度固定。
- 分隔符
- 在数据包中间用特定的分隔符来区分。
- 读取方接收数据时通过分隔符判断是否到达边界。
- 简单方便且不浪费空间,但必须保证分隔符不会出现在数据内容中。
- 消息头
- 在消息的头部添加一个长度字段,用于标识消息的长度。
- 接收方根据这个长度来读取响应长度的数据。
3. 说说 TCP 拥塞控制的步骤
前置知识点
- 名词解释
名称 | 说明 |
---|---|
慢启动阈值(ssthresh) | 这个值用于决定什么时候从慢启动转到拥塞避免阶段。 通常情况下,ssthresh 设置为丢包发生时的 cwnd 大小的一半 |
cwnd(拥塞窗口) | 表示发送方可以发送的最大字节数,依赖于网络的状态。 cwnd 会根据网络拥塞情况动态调整 |
RTT(往返时延) | RTT 时间变化对拥塞控制有直接影响, 因为 TCP 会根据 RTT 来调整发送速率 |
- 拥塞控制的目的
- 为了避免在网络中发生过度的拥塞,保证网络传输的稳定性和效率。
- 拥塞控制的目标
- 它的核心目标是根据网络状况动态调整发送速率,避免过多的数据包在网络中排队和丢失。
- 拥塞控制的实现方案
- TCP 拥塞控制通常通过调整 【拥塞窗口 (cwnd)】 的大小来实现,拥塞窗口决定了发送方在等待确认之前能够发送的最大数据量。
拥塞控制的四个主要算法
- 慢启动:通过指数增长
cwnd
快速增加发送速率。 - 拥塞避免:一旦达到阈值,采用线性增长
cwnd
以减少网络拥塞风险。 - 快速重传:基于重复 ACK 快速发现丢包并重传数据。
- 快速恢复:在丢包发生后,尽量减少窗口大小并恢复传输,避免返回到慢启动状态。
拥塞控制的步骤
-
慢启动 (Slow Start)
- 慢启动是 TCP 拥塞控制的第一个阶段,目的是快速增加拥塞窗口,以便尽快发现网络的承载能力,并避免过早进入拥塞状态。
- 此阶段的拥塞窗口
cwnd
从一个较小的值开始,逐步增加。- 初始时,
拥塞窗口(cwnd)
设置为 1 或 2(根据具体的实现,通常是 1)。 - 每当一个数据包被确认,
cwnd
就加倍,即指数增长。 - 慢启动阶段一直持续,直到
cwnd
达到一个阈值 ssthresh(慢启动阈值)或检测到网络阻塞。
- 初始时,
-
拥塞避免 (Congestion Avoidance)
- 当
cwnd
达到慢启动阈值(ssthresh
)后,TCP 进入拥塞避免阶段。 - 在此阶段,
cwnd
不再进行指数增长,而是采用线性增长的方式。- 每经过一个往返时间 (RTT),
cwnd
增加 1 个 MSS(最大报文段长度)。
- 每经过一个往返时间 (RTT),
- 拥塞避免阶段通常比慢启动阶段增长更慢,避免了激烈的拥塞反应,保持网络稳定性。
- 当
-
快速重传(Fast Retransmit)
- 接收方在收到一个失序的数据包时,会发送重复的 ACK 信号。
- 发送方在收到三个重复的 ACK 后,认为该 ACK 对应的数据包丢失,立即重传被认为丢失的报文段,无需等待超时。
- 这减少了重传的延迟,迅速应对数据丢失的情况。
-
快速恢复(Fast Recovery)
- 在快速重传之后, TCP 会进入到快速恢复阶段。
- 此时,TCP 不进入慢启动,
cwnd
不会回到慢启动阶段的初始值,而是减小cwnd
到ssthresh
的一半,然后进入拥塞避免阶段,开始线性增加cwnd
,以快速恢复到丢包前的传输速率。