一、滑动窗口

一、滑动窗口的由来

TCP以1个段为单位,每发一个段进行一次确认应答的处理。这样的传输方式有一个缺点。那就是,包的往返时间越长通信性能就越低。

刚才我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答.,收到ACK后再发送下一个数据段。这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候。

既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)为解决这个问题,TCP引入了窗口这个概念。即使在往返时间较长的情况下,它也能控制网络性能的下降。如图所示,确认应答不再是以每个分段,而是以更大的单位进行确认时,转发时间将会被大幅度的缩短。也就是说,发送端主机,在发送了一个段以后不必要一直等待确认应答,而是继续发送。

  • 窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。图中,窗口大小为4个段,也就是4000个字节。
  • 发送前四个段的时候, 不需要等待任何ACK, 直接发送。
  • 收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推。
  • 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉。
  • 窗口越大, 则网络的吞吐率就越高。


这种机制就被称为滑动窗口机制。

再具体一点就是:

二、滑动窗口存在的问题

1.滑动窗口的大小

2.数据包已经传输给对方,但是对方返回的ACK数据包丢失

数据包已经抵达, ACK被丢了。

这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认。

3.传输的数据包直接丢失,或者说是某个报文段丢失的情况


  • 当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001开始的数据"一样。
  • 如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送。
  • 这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中。


这种机制被称为 “高速重发控制”(也叫 “快重传”)。

二、流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端。
  • 窗口大小字段越大, 说明网络的吞吐量越高。
  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端。
  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度。
  • 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端。

接收端如何把窗口大小告诉发送端呢? 回忆我们的TCP首部中, 有一个16位窗口字段, 就是存放了窗口大小信息;那么问题来了, 16位数字最大表示65535, 那么TCP窗口最大就是65535字节么?

实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是 窗口字段的值左移 M 位。

三、拥塞控制


虽然TCP有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题。
因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的。
TCP引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。

  • 此处引入一个概念程为拥塞窗口。
  • 发送开始的时候, 定义拥塞窗口大小为1个数据段(1MSS)。
  • 每次收到一个ACK应答, 拥塞窗口加1。
  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的滑动窗口大小做比较, 取较小的值作为实际发送的窗口。
  • [ ] 像上面这样的拥塞窗口增长速度, 是指数级别的. “慢启动” 只是指初使时慢, 但是增长速度非常快。
  • 为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍。
  • 此处引入一个叫做慢启动的阈值。
  • 当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长。
  • 当TCP开始启动的时候, 慢启动阈值等于窗口最大值。
  • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1。

少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞,当TCP通信开始后, 网络吞吐量会逐渐上升,随着网络发生拥堵, 吞吐量会立刻下降。


但是这种拥塞窗口的大小一旦到达网络拥塞的情况时,拥塞窗口的大小会直接一下子变为慢启动时的阈值,即1个MSS,但是这种情况其实是不科学的,因为我一次丢包有可能是正常的,这种正常的情况的发生有可能是网络闪断了,当网络闪断的时候,拥塞串口的大小就会被置为1,然后再慢启动,再进行拥塞控制,针对这种情况,我们就需要一种快恢复的机制。

总结一下,TCP为了实现拥塞控制,总共采用了慢启动机制、拥塞避免机制、快重传机制和快恢复机制。

四、延迟应答

接收数据的主机如果每次都立刻回复确认应答的话,可能会返回一个较小的窗口。那是因为刚接收完数据,缓冲区已满。

当某个接收端收到这个小窗口的通知以后,会以它为上限发送数据,从而又降低了网络的利用率(这其实是窗口控制特有的问题,专门术语叫做糊涂窗口综合征)。为此,引入了一个方法,那就是收到数据以后并不立即返回确认应答,而是延迟一段时间的机制。

  • 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;
  • 但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了。
  • 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来。
  • 如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M。

窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率.。那么所有的包都可以延迟应答么? 肯定也不是;

  • 数量限制: 每隔N个包就应答一次。
  • 时间限制: 超过最大延迟时间就应答一次。

具体的数量和超时时间, 依操作系统不同也有差异,一般N取2,超时时间取200ms。

五、捎带应答


在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给服务器说了 “How are you”, 服务器也会给客户端回一个 “Fine, thank you”; 那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端。

接收数据以后如果立刻返回确认应答,就无法实现捎带应答。而是将所接收的数据传给应用处理生成返回数据以后进再进行发送请求为止,必须一直等待确认应答的发送。也就是说,如果没有启用延迟确认应答就无法实现捎带应答。延迟确认应答是能够提高网络利用率从而降低计算机处理负荷的一种较优的处理机制。

六、保活机制

七、延迟发送机制


总结

以上就是今天要讲的内容,本文详细介绍了传输层TCP协议保证传输效率和可靠传输的方法,网络提供了大量的方法供我们使用,非常的便捷,我们务必掌握。希望大家多多支持!另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。加油啊!

————————————————
版权声明:本文为CSDN博主「森明帮大于黑虎帮」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44918090/article/details/119619643

最后修改:2021 年 08 月 14 日
如果觉得我的文章对你有用,请随意赞赏