糊涂窗口综合征 SWS

糊涂窗口综合征

糊涂窗口综合征(Silly Window syndrome SWS)是一个发送端与接收端处理包不一致 导致出现接收端的通告窗口过小 再导致发送端窗口过小 从而导致产生大量的小数据包 这样的小数据包中头部占比大 导致传输效率低下 这样的行为就叫做糊涂窗口综合征

在网上看到一个例子可以很好的说明这个过程

假设接收方的缓冲区已经满了 而接受端程序每次只能处理很少 假设是1个字节 即接收端维护的接收窗口每次大小都只有一 倘若没有避免SWS的方法 从接收端返回的报文上的通告窗口大小只有1 那么发送方发送窗口也只能发送一个字节 那么在数据包中以最小的包来估计 IP20个字节 TCP20个字节 那么这个数据包大小为41 可以看出利用率及其低下 所以我们必须要避免这种情况

避免SWS

因为发送端和接收端都可能出现SWS 所以分别从两端进行避免

发送端

  1. 到达MSS个字节的报文段可以发送(Nalge算法 防止网络中出现大量小数据包)
  2. 发送报文达到通告窗口的最大值的一半时发送(针对于窗口较小的情况)

接收端

  1. 等待窗口增至一个MSS
  2. 等待窗口增至接收端缓冲区一半空闲

取两者之间最小值时再发送 否则发送窗口大小为零

延迟确认机制

在接收端收到数据时先不进行回复确认 接收端在确认收到的报文段之前一直等待 直到缓存有足够的空间为止 这样可以使得发送端在这期间窗口不进行滑动 这样就避免了SWS,而且还减少了网络中的数据包 其中延迟确认机制的超时时间应小于500ms 实践中最大取200ms(延迟确认机制和Nagle算法在一些特殊情况下可能造成死锁 Nagle算法在同一时刻只传递一个包 即遵循停等规程(stop-and-wait) 那么有可能接收端Nagle等待ACK 发送端延迟确认 即造成死锁 造成无谓的时延(Nagle因为停等规程本来时延就高于一般无Nagle的传输)

零窗口

既然接收端SWS避免会防止发送小的数据包 那么在接收端有数据但不足已发送时会发生什么呢?会出现零窗口的情况 即接收端回复的ACK中的窗口选项为0,因为流量控制是基于通告窗口的 窗口为零的时候发送端窗口为零 不再发送数据。当接收端程序处理完成后的数据到达SWS的时候 从零窗口中恢复 发送一个Update Window,因为窗口更新ACK中一般不包含数据 其不消耗序列号 所以是不可靠的,这就出现了一种问题 如果这个窗口更新丢失那么就会出现这样一种情况:接收端缓冲区空闲等待发送端数据 发送端等待接收端的窗口更新 即出现了死锁
其实这种情况解决的方法也很简单 即发送端持续性发送窗口探测(window probe) 因为窗口探测中包含一个字节的数据 占序列号 所以是可靠的 一定会得到一个窗口更新 其后的机制类似于karn算法

在接收端其实有时会出现一个问题 即SWS避免与避免窗口收缩的优先级的问题 可以想这样一种情况 即发送端的窗口大小假设为2000 发送端一次发送了1600 即接收端在接收到后只剩400了,这个时候难道会在回复的ACK中设置通告窗口为400吗 这不就违背了SWS避免吗 答案是会的 因为如果回复窗口大小为0就会使得发送端窗口收缩(shrink) 即滑动窗口右端左移动 而其中有可能有已发送未ACK的报文段,所以在避免窗口收缩和SWS避免间前者优先级更高

参考
TCP/IP详解 卷一
https://blog.csdn.net/qq_35733751/article/details/80224079
https://www.cnblogs.com/zhaoyl/archive/2012/09/20/2695799.html

发布了93 篇原创文章 · 获赞 69 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43705457/article/details/103413045