TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制

通过三次握手建立TCP连接后,双方就可以开始正式通信了,为了保证通信的高效可靠,TCP做了许多复杂的控制,如下

一、重传机制

网络情况错综复杂可能会出现丢包的情况,TCP会对丢失的数据进行重传,其重传机制有如下四种

1. 超时重传

超时重传是指发送数据后设置一个时间,超过这个时间没有收到ACK应答就重传(无论是发送的数据包丢失还是ACK应答丢失)。

超时时间RTO应该设置为略大于一个RTT(Round-Trip Time 往返时延),由于网络波动RTO也应是一个动态变化的值

2. 快速重传

如下图发送端发送了五个报文,但是中间Seq2丢失了因此接收端收到Seq3,4,5后回复了三个ACK2。快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。
TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制_第1张图片

3. SACK 方法

在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。

4. Duplicate SACK

Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。
TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制_第2张图片

二、滑动窗口

如果每发送一个数据都要进行一次确认应答,当上一个数据包收到了应答再发送下一个,这样显然效率不高。因此TCP引入了滑动窗口机制,在TCP头部中有一个window字段,表示告诉对方我当前还有多长的空闲缓冲区用于接收数据,对于发送端来说,用这个值减去还未收到ACK应答的数据长度,就是当前可以直接发出的数据,接收到ACK包后再继续向后滑动这个发送窗口

TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制_第3张图片
这样就可以无需等待应答而直接先发送一部分数据,并且中途若有 ACK 丢失,可以通过下一个确认应答进行确认。如下图,收到了ACK 700,就表示700前的数据都收到了,而无需重传数据。接收端在700前的数据没有全部收到是不会发送ACK 700的
TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制_第4张图片

三、流量控制

流量控制就是使用上述滑动窗口来控制数据发送速率,通过接收端的window值减去还未收到ACK应答的数据长度,就是当前可以直接发出的数据。

1. 窗口关闭

如果接收端窗口大小为 0 时,就会给发送端一个window值为0的报文,发送端则停止发送数据,直到接收方处理完数据有空余缓冲区,会向发送方通告一个窗口非 0 的 ACK 报文,发送方才继续发送数据,这称为窗口关闭。但是如果这个通告窗口非0的 ACK 报文在网络中丢失了,就会造成双方无限等待对方的情况,为了解决这个问题,TCP 为每个连接设有一个持续定时器,只要 TCP 连接一方收到对方的零窗口通知,就启动持续计时器。如果持续计时器超时,就会发送窗口探测 ( Window probe ) 报文,而对方在确认这个探测报文时,给出自己现在的接收窗口大小。

2. 糊涂窗口综合症

如果接收方太忙了,来不及取走接收窗口里的数据,那么就会导致发送方的发送窗口越来越小。到最后,如果接收方腾出几个字节并告诉发送方现在有几个字节的窗口,而发送方会义无反顾地发送这几个字节,这就是糊涂窗口综合症。为解决这个问题:

  • 接收方策略:不通告小窗口,当「窗口大小」小于 min( MSS,缓存空间/2 ) ,也就是小于 MSS 与 1/2 缓存大小中的最小值时,就会向发送方通告窗口为 0,也就阻止了发送方再发数据过来。

  • 发送方策略:使用 Nagle 算法,该算法的思路是延时处理,要等到窗口大小 >= MSS 并且 数据大小 >= MSS,或者收到之前发送数据的 ack 回包,才发送数据。不过前提是接收方也开启了不通告小窗口的策略

四、拥塞避免

在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大。所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。那么怎么知道当前网络是否出现了拥塞呢?其实只要「发送方」没有在规定时间内接收到 ACK 应答报文,也就是发生了超时重传,就会认为网络出现了拥塞。

那么根据拥塞情况发送端会维护一个拥塞窗口的状态变量cwnd,它会根据网络的拥塞程度动态变化的。那么实际发送窗口的值就是也就是拥塞窗口和接收窗口中的最小值。

拥塞控制主要是如下四个算法:

1. 慢启动

TCP 在刚建立连接完成后,首先是有个慢启动的过程,这个慢启动的意思就是一点一点的提高发送数据包的数量,如果一上来就发大量的数据,这不是给网络添堵吗?

慢启动的算法记住一个规则就行:当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1个MSS。因此拥塞窗口长度会进行一个指数级增长,当到达慢启动门限 ssthresh后就会开始使用拥塞避免算法

2. 拥塞避免

拥塞避免的规则是:每当收到一个 ACK 时,cwnd 增加 1/cwnd。例如若ssthresh 为 8:当 8 个 ACK 应答确认到来时,每个确认增加 1/8,8 个 ACK 确认 cwnd 一共增加 1,于是这一次能够发送 9 个 MSS 大小的数据,变成了线性增长
TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制_第5张图片
就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。当触发了重传机制,也就进入了「拥塞发生算法」。

3. 拥塞发生

当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:超时重传和快速重传。这两种使用的拥塞发送算法是不同的,接下来分别来说说。

(1)发生超时重传的拥塞发生算法

  • ssthresh 设为 cwnd/2
  • cwnd 重置为初始值

(2)发生快速重传的拥塞发生算法

  • cwnd = cwnd/2 ,也就是设置为原来的一半;
  • ssthresh = cwnd;
  • 进入快速恢复算法

4. 快速恢复

快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,如果后续你还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像 RTO 超时那么强烈。

  • 后续又收到3个重复的ACK后,拥塞窗口 cwnd = ssthresh + 3;
  • 重传丢失的数据包;
  • 如果再收到重复的 ACK,那么 cwnd继续1;
  • 如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;

先恢复cwnd是为了能快速把丢失的包重传出去,重传完了再降cwnd是为了减缓拥塞
TCP的数据传输机制:重传机制、滑动窗口、流量控制、拥堵控制_第6张图片

你可能感兴趣的:(#,计算机网络,tcp/ip,网络,网络协议)