TCP的流量控制

本文介绍了TCP协议中的流控机制,包括慢启动与拥塞避免算法,以及快速重传和快速恢复算法。慢启动通过逐步增加拥塞窗口来适应网络状态,而拥塞避免则更加平缓地增长窗口大小。快速重传机制允许发送方在接收到三个重复的ACK后立即重传疑似丢失的分组。
 
1. 前言
 
TCP是具备流控和可靠连接能力的协议,为防止TCP发生拥塞或为提高传输效率,在网
络发展早期就提出了一些相关的TCP流控和优化算法,而且也被RFC2581规定是每个
TCP实现时要实现的。
 
本文中,为求方便把将“TCP分组段(segment)”都直接称为“包”。
 
2. 慢启动(slow start)和拥塞避免(Congestion Avoidance)
 
慢启动和拥塞避免是属于TCP发送方必须(MUST)要实现的,防止TCP发送方向网络传入大量的突发数据造成网络阻塞。

先介绍几个相关参数,是在通信双方中需要考虑但不在TCP包中体现的一些参数:

拥塞窗口(congestion window,cwnd),是指发送方在接收到对方的ACK确认前向允许网络发送的数据量,数据发送后,拥塞窗口缩小;接收到对方的ACK后,拥塞窗口相应增加,拥塞窗口越大,可发送的数据量越大。拥塞窗口初始值的RFC2581中被规定为不超过发送方MSS的两倍,而且不能超过两个TCP包,在RFC3390中更新了初始窗口大小的设置方法。

通告窗口(advertised window,rwnd),是指接收方所能接收的没来得及发ACK确认的数据量,接收方数据接收后,通告窗口缩小;发送ACK后,通告窗口相应扩大。

慢启动阈值(slow start threshold, ssthresh),用来判断是否要使用慢启动或拥塞避免算法来控制流量的一个参数,也是随通信过程不断变化的。

当cwnd < ssthresh时,拥塞窗口值已经比较小了,表示未经确认的数据量增大,需要启动慢启动算法;当cwnd > ssthresh时,可发送数据量大,需要启动拥塞避免算法。

拥塞窗口cwnd是根据发送的数据量自动减小的,但扩大就需要根据对方的接收情况进行扩大,慢启动和拥塞避免算法都是描述如何扩大该值的。

在启动慢启动算法时,TCP发送方接收到对方的ACK后拥塞窗口最多每次增加一个发送方MSS字节的数值,当拥塞窗口超过sshresh后或观察到拥塞才停止算法。

启动拥塞避免算法时,拥塞窗口在一个连接往返时间RTT内增加一个最大TCP包长度的量,一般实现时用以下公式计算:
      cwnd += max(SMSS*SMSS/cwnd, 1)            (2.1)
SMSS为发送方MSS。

TCP发送方检测到数据包丢失时,需要调整ssthresh,一般按下面公式计算:
      ssthresh = max (FlightSize / 2, 2*SMSS)    (2.2)
其中FlightSize表示已经发送但还没有被确认的数据量。
 
3. 快速重传(fast retransmit)和快速恢复(fast recovery)

TCP接收方收到错序的TCP包时要发送复制的ACK包回应,提示发送方可能出现网络丢包;发送方
收到连续3个重复的ACK包后启动快速重传算法,根据确认号快速重传那个可能丢失的包而不必等
重传定时器超时后再重传,普通的重传是要等到重传定时器超时还没收到ACK才进行的。这个算
法是TCP发送方应该(SHOULD)实现的,不是必须。TCP发送方进行了快速重传后进入快速恢复阶段
,直到没再接收重复的ACK包。

快速重传和快速恢复具体过程为:
1. 当收到第3个重复的ACK包时,ssthreh值按公式2.2重新设置;
2. 重传丢失的包后,将拥塞窗口cwnd设置为sshresh+3*SMSS,人工扩大了拥塞窗口;
3. 对于每个接收到的重复的ACK包,cwnd相应增加SMSS,扩大拥塞窗口;
4. 如果新的拥塞窗口cwnd值和接收方的通告窗口值允许的话,可以继续发新包;
5. 当收到下一个ACK确认了新数据时,将cwnd大小调整为sshresh,减少窗口;对接收方
   来说,接收到重发的TCP包后就要发此ACK确认当前接收的数据。
 
4. 结论
这些算法重点在于保持网络的可靠性和可用性,防止网络阻塞造成的网络崩溃,是相对
比较保守的。 
### TCP流量控制的实现方式 TCP流量控制的核心目标是确保发送方的数据传输速率不会超过接收方的处理能力,从而避免数据丢失和网络拥塞。以下是TCP流量控制的主要实现方式: #### 1. 滑动窗口机制 TCP通过滑动窗口机制来实现流量控制。接收方在确认消息中会告知发送方当前可用的接收窗口大小(即 `Window Size`),该值表示接收方还能接收多少字节的数据[^1]。发送方根据接收方提供的窗口大小调整自身的发送速率,以确保不会发送超出接收方处理能力的数据量。 #### 2. 动态调整窗口大小 早期的TCP协议中,接收窗口的大小是固定的,但随着网络的发展,固定大小的窗口变得不灵活,成为性能瓶颈之一。现代TCP协议通过动态调整窗口大小来适应网络条件的变化。例如,当接收方缓存空间充足时,可以增大窗口大小;当缓存接近满载时,则减小窗口大小[^2]。 #### 3. 确认与反馈机制 TCP使用确认机制(ACK)来实现可靠的数据传输。每当接收方成功接收到数据后,会向发送方发送一个确认消息,并附带当前的接收窗口大小。发送方根据这些反馈信息调整自己的发送策略[^5]。 #### 4. 缓冲区管理 接收方维护一个接收缓冲区,用于暂时存储尚未被应用层读取的数据。如果接收方的应用程序读取数据的速度较慢,导致缓冲区逐渐填满,接收方会通过减小窗口大小通知发送方降低发送速率。反之,如果缓冲区有足够空间,接收方会增大窗口大小以允许发送方加快传输速度[^4]。 #### 5. Nagle算法的影响 Nagle算法是一种优化小数据包传输的机制,它会将多个小数据包合并成一个较大的数据包再发送,从而减少网络开销。然而,这种机制可能会引入延迟,因为发送方需要等待确认消息才能发送后续数据。虽然Nagle算法主要用于解决小数据包问题,但它也可能间接影响流量控制的效果[^4]。 ```python # 示例:简单模拟TCP滑动窗口机制 class TCPFlowControl: def __init__(self, window_size): self.window_size = window_size # 接收窗口大小 self.buffer = [] # 接收缓冲区 def receive_data(self, data): if len(data) <= self.window_size - len(self.buffer): self.buffer.extend(data) return True else: return False # 超出窗口大小,拒绝接收 def read_data(self, size): data = self.buffer[:size] del self.buffer[:size] return data # 使用示例 tcp = TCPFlowControl(window_size=100) data_received = tcp.receive_data(b"Hello World") # 尝接收数据 if data_received: print("Data received successfully.") else: print("Failed to receive data due to window size limitation.") ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值