专栏首页Coding迪斯尼TCP窗口调整与数据流控制以及病态窗口症状

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

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接收窗口,告知对方暂时停止发送数据,等到可用缓冲区恢复到原来一半以上时再通知对方发送数据。同时数据发送方要主动将数据积攒到足够多后才发送,避免反复发送小量数据导致网络效率下降。

本文分享自微信公众号 - Coding迪斯尼(gh_c9f933e7765d),作者:陈屹

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • HTTP协议原理及java实现:数据的基本传输模式

    zu说到基于TCP协议的上层协议,绝对绕不开的是HTTP协议,在其设计之初,设计者绝对想不到该协议具备的灵活性能够让其成为最广泛使用的TCP上层协议,在我看来H...

    望月从良
  • 详解TCP数据包中SYN,ACK字段与数据发送的关联

    在TCP协议中,为了确保数据能稳定发送,协议使用数据包中的syn,ack两个字段来监控数据是否正确发生和接收,本节我们看看这两个字段如何保证数据的平稳传输。

    望月从良
  • HTTP协议的状态码解读

    当客户端把请求发送给服务器后,对方会根据处理结果返回一系列HTTP数据包。其中第一行就用给定格式表明服务器对请求处理的结果。第一行包括三部分信息,第一部分是一个...

    望月从良
  • java socket通信

    (图片来源:https://www.cnblogs.com/itfly8/p/5844803.html)

    IT云清
  • 02 python网络爬虫《Http和H

        Http协议就是服务器(Server)和客户端(Client)之间进行数据交互(相互传输数据)的一种形式。

    py3study
  • iOS-修改系统Tabbar背景色

    用户1890628
  • An overview of the Web(Web概述)

    C/S结构和B/S结构是当今世界网绍程序开发体系结构的两大主流.目前,这两种结构都有自己的市 场份和客户群。但是,这两种体系结构又各有各的优点和缺点,下面将从...

    凌川江雪
  • 数据可视化工具Visdom

    Visdom,用于创建、组织和共享实时丰富数据可视化的灵活工具。支持Python。

    磐创AI
  • LoRaServer 笔记 1.3 源码编译

    另外整个编译过程绝对还是会出现包被墙的情况,9102年了,GO 1.11 有个 moudule 可以很方便的处理这些情况。大家可以处理下 go.mod 的文件,...

    twowinter
  • MySQL 5.7 多主一从的复制结构

    多源复制的作用 MySQL 5.7.6 开始,添加了一个新特性:多源复制 Multi-Source Replication 可以让你同时从多个master中并行...

    dys

扫码关注云+社区

领取腾讯云代金券