TCP滑动窗口

TCP滑动窗口

概述

TCP进行数据发送,为了提高数据传输的效率,采用了一种叫做滑动窗口的机制来进行数据发送。

滑动窗口用于做流量控制与乱序重排

  • 保证TCP的可靠性
  • 保证TCP的流控特性

RTT和RTO

  • RTT
    发送一个数据包到收到对应的ACK所花费的时间
  • RTO
    重传时间间隔

窗口数据的计算过程

在这里插入图片描述

接收方还能接收的窗口大小
AdvertisedWindow = MaxRcvBuffer - (LastByteRcvd - LastByteRead)

发送方还能发送的窗口大小
EffectiveWindow = AdvertisedWindow - (LastByteSent - LastByteAcked)

滑动窗口图示

发送方
在这里插入图片描述
在这里插入图片描述

接收方
在这里插入图片描述

流量控制

滑动窗口机制能防止发送方无脑的发送数据,导致接收方缓冲区被填满而无法接收新的数据。

如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。

可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。

下面举个栗子,为了简单起见,假设以下场景:

客户端是接收方,服务端是发送方。
假设接收窗口和发送窗口相同,都为200,且在整个传输过程中都保持相同的窗口大小,不受外界影响。
在这里插入图片描述
根据上图的流量控制,说明下每个过程:

  1. 客户端向服务端发送请求数据报文。这里要说明下,本次例子是把服务端作为发送方,所以没有画出服务端的接收窗口。
  2. 服务端收到请求报文后,发送确认报文和80字节的数据,于是可用窗口 Usable减少为120字节,同时SND.NXT指针也向右偏移80字节后,指向321,这意味着下次发送数据的时候,序列号是321。
  3. 客户端收到80字节数据后,于是接收窗口往右移动80字节,RCV.NXT也就指向321,这意味着客户端期望的下一个报文的序列号是321,接着发送确认报文给服务端。
  4. 服务端再次发送了120字节数据,于是可用窗口耗尽为0,服务端无法在继续发送数据。
  5. 客户端收到120字节的数据后,于是接收窗口往右移动120字节,RCV.NXT 也就指向441,接着发送确认报文给服务端。
  6. 服务端收到对80字节数据的确认报文后,SND.UNA指针往右偏移后指向321,于是可用窗口Usable增大到80。
  7. 服务端收到对120字节数据的确认报文后,SND.UNA指针往右偏移后指向441,于是可用窗口Usable增大到 200。
  8. 服务端可以继续发送了,于是发送了160字节的数据后,SND.NXT指向601,于是可用窗口Usable减少到40。
  9. 客户端收到160字节后,接收窗口往右移动了160字节,RCV.NXT也就是指向了601,接着发送确认报文给服务端。
  10. 服务端收到对160字节数据的确认报文后,发送窗口往右移动了160字节,于是SND.UNA指针偏移了160后指向601,可用窗口Usable也就增大至了200。

死锁问题

引起死锁的原因

接收方在发送确认报文时可能会出现还能接收的窗口大小为零的情况,当发送rwnd=0的确认报文后不久,接收方的接收缓存因为读取了部分数据而又有了一些存储空间。于是接收方会发rwnd>0的报文段,然而这个报文段在传送中丢失了。此时,发送方会一直等待收到接收方发送的非零窗口的通知,而接收方也一直等待发送方发送的数据,就产生死锁了。

解决死锁的机制

TCP为每个连接设有一个持续计时器。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器,若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1字节的数据),而对方就在确认这个探测报文段时给出当前的窗口值。

### TCP滑动窗口协议的工作机制 TCP滑动窗口是一种流量控制机制,旨在优化网络性能并防止发送方过载接收方缓冲区。其核心思想是通过动态调整窗口大小来平衡数据传输速率与网络条件之间的关系。 #### 基本概念 滑动窗口的核心在于维护一个“窗口”,该窗口表示当前允许发送的数据量范围。这个窗口会随着确认消息的到来而向前移动[^1]。具体来说: - **发送窗口 (Send Window)**:定义了发送方可以在未收到确认的情况下连续发送多少字节的数据。 - **接收窗口 (Receive Window)**:由接收方通告给发送方,表明它可以接受的最大数据量。 当接收到新的ACK(Acknowledgment)包时,发送方更新自己的发送窗口位置,并继续发送新数据直到达到窗口边界。 #### 实现细节 以下是TCP滑动窗口的一些重要实现细节: 1. **序列号管理** 每个TCP报文段都有唯一的序号,这些序号用于跟踪哪些部分已被成功传递以及哪些需要重传。初始序列号通常随机生成以增强安全性。 2. **拥塞控制集成** 尽管严格意义上属于另一个领域,但实际应用中,TCP的拥塞控制算法(如慢启动、拥塞避免阶段等)直接影响到滑动窗口的行为模式。例如,在检测到丢包事件后可能会缩小cwnd(Congestion Window),从而间接影响rwnd(Receiver Window)。这种交互确保即使在网络状况不佳时也能维持一定程度的服务质量。 3. **超时处理与快速重传** 如果某个特定分组长时间未能得到回应,则触发定时器到期进而引发整个连接层面的动作——重新尝试传送丢失片段;与此同时如果接连收到三个重复ack则立即执行fast retransmit而不必等待timeout发生。 4. **双向通信特性支持** 不同于单向流控方案仅关注一方如何调节另一方行为,tcp swp同时考虑两端需求并通过各自独立却又相互关联的方式完成整体协调工作。 ```python class TCPSlidingWindow: def __init__(self, initial_seq_num=0, max_window_size=65535): self.send_base = initial_seq_num # Next byte expected to be acknowledged. self.next_seq_num = initial_seq_num # Next byte we can send. self.max_window_size = max_window_size # Maximum size of the window. def update_send_window(self, ack_number): """Update the sending window based on acknowledgment.""" if ack_number > self.send_base: self.send_base = ack_number def has_space_to_send(self): """Check whether there's space within the current window to transmit more data.""" return (self.next_seq_num - self.send_base) < self.max_window_size def advance_next_sequence(self, bytes_sent): """Advance sequence number after successfully transmitting some amount of data.""" self.next_seq_num += bytes_sent ``` 上述代码展示了一个简化版的TCP滑动窗口逻辑框架,其中包含了基本的操作函数比如`update_send_window`, `has_space_to_send` 和 `advance_next_sequence`. --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值