TCP滑动窗口

205 阅读5分钟

滑动窗口

大家都口口相传TCP是安全的可靠的网络传输协议。

要做到可靠要解决很多问题,其中一个问题就是:发送方能力和接收方能力不一样怎么处理? 这次要讨论的TCP滑动窗口的技术就是解决了这样一个问题的,保证了发送方能和接收方保证相同的大小。

那为什么要解决这样一个问题呢?因为如果发送方发送速度太快,会出现接收方数据overflow,这就会浪费流量导致网络拥塞等。

TCP是如何保证数据包的次序?

TCP是如何保证数据的有序性的呢?

答:发送方发送一个包1,这时候等待确认包1。确认包1以后才发送包2,确认包2。以此下去,直到发送完所有的数据包。问题:吞吐量非常低。

如何提高吞吐量呢?

们同时发送几个包过去一起确认,这样速度会不会更快呢?

答: 2个包一起发送过去,一起回来,所以总共耗时一个来回RT,原本需要2个来回的时间现在只需要一个来回。速度肯定有提升的。

如何平衡吞吐量呢

确定一次发送多个数据包过去会提示整体速度,那么一次发送多少合适?

为了确定的准备的数据包数量,出现了滑动窗口。

图1:

实现

图2:

正常情况

窗口滑动的过程:

图1中1-3号的数据包已经完成了发送并且接收到了ACK,标记为灰色。4-7为发送了但是没有收到ACK,标记为黄色,绿色的部分是待发送的,而白色的部分是不在窗口内部等待发送到的数据包。

图2中,当4号数据包收到了ack以后,窗口向右移动一格,4号数据包变成已发送状态,把11号数据包读进缓存。

这是发送方角度的窗口移动,并且他的大小是变动的,取决于接受方返回的rwnd (receiver window)大小。也就是说,每次发送方接收到ack的同时,会接受一个rwnd大小,来实时改变滑动窗口大小。这样就可以保证发送方和接受方能力大致匹配。

上面是理想情况,但是数据包在网络上传输时,往往情况复杂。

介绍下TCP 在处理错误或者优化时的几种方式:

重传机制:超时重传,快速重传,SACK,D-SACK

超时重传:

RTT(Round-Trip Time 往返时延):表示数据从网络一端传到另外一端的往返时间。

RTO(Retransmission Timeout): 发送端长时间没有得到应答重新发起请求的时间--- 超时重传

RTO 应该略大于RTT

超时重传是以时间为驱动的,时间应该略大于往返时间

快速重传:

快速重传则是以数据为驱动的

发送包以后一般会收到ack确认包,当连续没有收到某一个确认包的时候,会触发重传机制。

SACK方法

会在TCP的头部字段里面加一个SACK的字段,该字段会缓存接受到哪些发送方的数据包,这样就可以知道哪些数据没有收到,可以重传丢失的数据

选择性确认

具体的可以参考:你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了 - 掘金

拥塞窗口机制:慢启动、快速恢复、拥塞避免

慢启动:

所谓慢启动就是在TCP刚建立连接的时候,一点一点提高提高发送数据包的数量。如果一上来就传大量的数据包,这是不准确的。

慢启动的算法:当发送方每收到一个ACK,就拥有窗口的大小就会加1,2会变4,4会变8,8会变16成指数增长。

那么慢启动会一直增下去吗?

肯定不是,会有一个叫慢启动门限的状态变量 ssthresh

当 cwnd < ssthresh时,会使用 【慢启用】 算法。

当 cwnd >= ssthresh时,就会使用【拥塞避免算法】

拥塞避免算法

拥塞避免:顾名思义就是避免拥塞,就是要降低发送数据包的数量。从之前的指数增长变成了线性增长。怎么叫线性增长呢?之前慢启动是1个ACK都会增加让cwnd增加一个,就像细胞分裂一般。一变二,而变4。现在拥塞避免纬度就是轮次。当完成一个轮次cwnd增加一个。也就是线性的增长了。

拥塞避免

拥塞发生

当发生了 【超时重传】,则就会使用拥塞发生算法。

该算法可以简单理解,回到了刚建立TCP连接时候的慢启动。

ssthresh设置为了 cwnd / 2,并且cwnd 大小重制为了 1.

快速恢复

快速恢复可以和拥塞发生相比,没有一夜回到解放前,而是比较缓和的下降然后缓和的上升。

  • cwnd = cwnd/2 ,也就是设置为原来的一半;
  • ssthresh = cwnd;

提纲

参考:

  1. 你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了 - 掘金

  2. 一篇带你读懂TCP之“滑动窗口”协议 - 掘金