您的位置:首页 > 理论基础 > 计算机网络

TCP窗口调整与数据流控制以及病态窗口症状

2020-04-07 12:09 2679 查看

TCP协议主要依赖不断调整窗口大小来保证数据收发吞吐率。在三次握手时,客户端会告诉服务器自己一次能接收数据量的大小,这就对应客户端的接收窗口以及服务器的发送端口。同理服务器也会告知客户端它一次能接收的数据量,这就成为客户端的发送窗口以及服务器端的接收窗口。

TCP数据发送的灵活之处在于,发送窗口或接收窗口可以根据数据收发的情况不断调整。我们看一种具体情况,假设服务器一次能接收360字节,当客户端把数据发送到服务器时,服务器需要采取两个动作,一是回发ACK包,告知对方接收到数据,二是把数据从缓冲区中推送给上层应用,问题在于第二步往往会有延迟,这就使得服务器不是每次都能接收360字节的数据,于是他就得告诉客户端调整数据发送量以免发送数据过多造成服务器的缓冲区溢出。

数据发送双方根据当前接收缓冲区大小不断调整接收窗口的过程就叫数据流控制,这种控制对数据收发效率非常重要,它能让双方按照对方当前容量来调整数据量大小从而保障数据传输效率,窗口调整以保证数据传输率的过程可如下图所示:

如图所示,服务器一次能接收360字节,因此客户端将它的发送窗口大小设置为360,第一次它向服务器发送140字节,服务器接收到数据后由于它本身还要忙于处理其他请求,因此不能及时将接收的140字节数据全部传递给上层应用程序。假设它只来得及将40字节的数据传递给上层应用,因此缓冲区中还存有100字节,可用空间就是260,于是他回复ACK包时要告知客户端此时服务器的接收窗口是260,于是客户端下次发送数据时就会保证数据大小不超过260.

接下来客户端继续向服务器发送180字节数据,于是服务器的缓冲区又消耗掉180字节,只剩下80字节,于是回复给客户端的ACK包中要告知对方接收窗口调整为80字节。然后客户端再次发送80字节数据,服务器接收后缓冲区全部用尽,此时它不能继续接收新数据,这种情况就叫接收窗口关闭。

假设服务器接收到140字节,此时由于服务器内存紧缺,因此需要从当前缓冲区中拿出120字节作为他用,于是当前接收缓冲区大小变成240,而且其中140字节已经用来接收客户端发来的数据,因此当前服务器最多只能接收100字节的数据。问题在于客户端根本不知道服务器端发生这种变化,它以为服务器还能继续接收220字节数据,于是在得到服务器回复ACK包前又发送220字节数据,由于服务器只能接收100字节,于是会导致第二次客户端发送数据中,120字节数据只能接收100字节,后面的20字节丢失然后客户端只能重发。由于这种情况的应对比较麻烦,我们后面实现时还是以方便原则,在牺牲效率的基础上保证简单性。

还有一种情况我们需要考虑的是,如果服务器端缓冲区全部耗尽,这时它会在回复的ACK包中将自己的接收窗口设置为0,此时客户端就只能等待而不能发生任何数据,只有等到服务器再次发来ACK,里面接收窗口大于0才能发送数据。这里有可能出现的问题是,第二次发送的ACK包可能因为网络原因而丢失,于是客户端就无法知道此时服务器有了可用缓冲区,过段时间后客户端以为服务器端出现问题,因此它会主动 关闭掉连接。为了防止这种情况发送,客户端需要周期性的向服务器发送探测包,其目的是让服务器返回包含当前接收窗口的ACK包,探测包通常不会包含任何数据。

还有一个问题需要考虑就是TCP数据传输中会出现的”病态窗口症状“。对应现象是TCP数据包每次发送的数据量都很小,使得一块数据需要分成多次发送导致吞吐效率严重降低,我们看一个具体实例,假设数据包一次最大发送数据量是260字节,同时服务器端的接收窗口也是360字节,假设客户端有很多数据需要发送给服务器,它第一次发送360字节,如果此时服务器效率不高,它只能把第一次接收到的数据中的120字节传递给上层应用,那么此时它的接收窗口只有120字节。

于是服务器在回复的ACK包中会将接收窗口设置为120,客户端收到后立马又将120字节数据发送过去。当服务器接收到120字节时服务器正好将当前缓冲区中的40字节传递给应用层,于是接收这120字节后缓冲区用去280字节,此时服务器又得将接收窗口缩小为80字节,于是当客户端收到ACK包后又立刻发过去80字节,当80字节抵达服务器时,服务器把27字节传递给上层应用,于是此时缓冲区被占据293字节,于是接收窗口变成67字节,就这样服务器每次从缓冲区中拿走的数据量是接收量的三分之一,于是多次数据发送后接收窗口越来越小,最坏情况下服务器每次将1字节提交给上层应用,于是客户端每次只能向服务器发送1字节,这就是病态滑动窗口症状,我们可以通过下图来进一步了解病态滑动窗口症状:

病态滑动窗口症状其实是TCP协议没有现在数据发送下限导致,解决办法是禁止任何一方不断的缩写接收窗口大小,如果一方缓冲区过小那就直接将接收窗口设置为0,防止对方继续发送数据,通常情况下当可用缓冲区降至原来一半以下时就向对方发送0接收窗口,告知对方暂时停止发送数据,等到可用缓冲区恢复到原来一半以上时再通知对方发送数据。同时数据发送方要主动将数据积攒到足够多后才发送,避免反复发送小量数据导致网络效率下降。

更详细的讲解和代码调试演示过程,请点击链接

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:

  • 点赞 3
  • 收藏
  • 分享
  • 文章举报
tyler_download 博客专家 发布了351 篇原创文章 · 获赞 310 · 访问量 42万+ 他的留言板 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: