窗口的变化有三种:窗口合拢,窗口张开,窗口收缩。但是对于窗口合拢和窗口张开已经详细介绍过。
对于接收窗口来说,RFC是不建议让窗口收缩的,因为接收方的rwnd会导致发送方的发送窗口收缩(发送方的发送窗口是根据接收方发送的rwnd来设置的)。某些实现是不允许发送窗口收缩的,为了防止发送窗口收缩,接收方的新的ack号和新的rwnd,最近的ack号和最近的rwnd始终满足以下条件:
新
的
a
c
k
号
+
新
的
r
w
n
d
≥
最
近
的
a
c
k
号
+
最
近
的
r
w
n
d
新的ack号 + 新的rwnd ≥ 最近的ack号 + 最近的rwnd
新的ack号+新的rwnd≥最近的ack号+最近的rwnd
在上面这个不等式中,新的ack号 + 新的rwnd代表窗口右边沿的新位置,而最近的ack号 + 最近的rwnd代表窗口右边沿原来的位置。只要满足这个公式,就说明窗口的右边沿永远也不可能向左移动
。
我们通过下面一个示例来说明为什么有些实现要遵守上面这个公式的原因,同时间接说明了为什么不允许窗口收缩。
图1中的是发送方收到的最近的一个ack和rwnd,其中206 - 214是发送方下一次要发送的数据,图2是发送方发送了206 - 214数据之后的状态,其中206 - 209是已经确认并清除的数据。但是最新的ack为210,最新的rwnd = 4,那么根据不等式:210 + 4 < 206 + 12,计算出新的窗口右边沿的位置是小于最近的窗口右边沿的位置,这显然是不满足不等式的条件(大家可以对比一下图1和图2中右边沿的位置),发送窗口的位置就会如图2中所示。
这会产生一个问题:原本已经发生出去的214字节数据在发送窗口右边沿的外面(按理来说,214字节数据已经发送出去,这时,应该在窗口中等待被确认才是,但是由于窗口收缩,导致214字节数据在窗口外面)
,这也是为什么要用这个不等式来强制让接收方的接收窗口的右边沿的位置保持在217位置的原因。为了防止这种情况发生,接收方应该等待进程读走更多字节数据(增大rwnd空间),来满足上面这个不等式的条件。