面试题答案
一键面试拥塞控制算法阐述
- 慢启动(Slow Start)
- 原理:发送方在开始发送数据时,先将拥塞窗口(cwnd)初始化为一个较小的值(通常为1个最大段大小MSS)。每收到一个确认(ACK),就将cwnd增加1个MSS。这样cwnd会以指数级的速度增长,快速增加发送速率。
- 适用场景:在网络刚开始传输数据或者网络空闲一段时间后重新传输数据时,能快速探测网络的可用带宽。
- 拥塞避免(Congestion Avoidance)
- 原理:当cwnd达到慢启动门限(ssthresh)时,进入拥塞避免阶段。此时每收到一个ACK,cwnd增加1/cwnd个MSS。也就是说,cwnd的增长速度变为线性增长,以避免网络拥塞。
- 适用场景:当网络已经接近拥塞边缘时,通过线性增长cwnd来维持网络的稳定传输。
- 快重传(Fast Retransmit)
- 原理:当发送方连续收到3个相同的ACK时,就认为有一个数据包丢失,此时不等重传定时器超时,就立即重传丢失的数据包。
- 适用场景:在网络出现少量丢包时,快速重传丢失的数据包,减少数据传输延迟。
- 快恢复(Fast Recovery)
- 原理:当执行快重传后,将ssthresh设置为当前cwnd的一半,同时将cwnd设置为ssthresh加上3倍的MSS(因为收到了3个重复ACK),然后进入拥塞避免阶段,cwnd线性增长。这样可以在快速恢复丢失数据包的同时,也对网络拥塞做出一定反应。
- 适用场景:在快重传之后,快速调整发送速率,避免网络拥塞进一步恶化。
算法协同工作分析
- 网络空闲或初始阶段:慢启动开始,cwnd指数增长,快速探测网络带宽。
- 接近拥塞阶段:到达ssthresh后进入拥塞避免,cwnd线性增长,防止网络拥塞。
- 少量丢包:触发快重传,快速重传丢失包,同时快恢复调整cwnd和ssthresh,进入拥塞避免继续传输,维持网络稳定。
- 严重拥塞(超时重传):将ssthresh设置为当前cwnd的一半,cwnd重新设置为1个MSS,重新进入慢启动,逐步恢复网络传输。
代码层面实现(以Python和TCP socket为例,简化示例)
import socket
# 初始化参数
cwnd = 1 # 拥塞窗口
ssthresh = 16 # 慢启动门限
MSS = 1024 # 最大段大小
# 创建TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', 12345))
# 模拟数据发送
data = b'0' * MSS
while True:
# 发送数据
sent = sock.send(data)
if sent == 0:
raise RuntimeError("socket connection broken")
# 模拟接收ACK
try:
ack = sock.recv(1024)
if ack:
if cwnd < ssthresh:
cwnd = cwnd + 1
else:
cwnd = cwnd + 1 / cwnd
# 调整下次发送数据大小
data = b'0' * int(cwnd * MSS)
except socket.timeout:
# 超时重传
ssthresh = cwnd / 2
cwnd = 1
data = b'0' * MSS
# 这里省略快重传和快恢复的详细模拟,实际需要根据重复ACK等情况实现
上述代码是一个非常简化的TCP拥塞控制算法实现示例,实际在操作系统内核中的TCP实现会更加复杂,涉及到很多底层细节和优化。