努力经营当下,直至未来明朗!
一个人最大的痛苦来源于对自己无能的愤怒!
Hi,这里是不想秃头的宝贝儿!

本文主要内容是 传输层中TCP相关机制的补充:滑动窗口、流量控制、拥塞控制。
也很重要!(重点内容会重点标出)
TCP能够保证可靠传输,但是失去了效率,那么如何尽可能提高传输效率呢?(但是注意:再怎么提高都是无法超过UDP效率的)
滑动窗口:提高TCP传输效率的有效机制
没有引入滑动窗口,只是一个朴素的确认应答

主机A大量的时间都消耗在了等待ACK上,则提升效率的方法就是不等ACK了,直接往下继续发送(但其实不是完全不等,而是每次发送一波消息,然后等一波ACK,然后再发送一波消息)
把不需要等待就可以直接发送的数据的量,称为“窗口大小”
滑动窗口下:如图批量发送3条数据,批量接收3条ACK,此处的窗口大小是300(以字节为单位)

注意:主机A是收到了一个ACK就继续发一条数据,而不是等所有的ACK都到了才统一发下一组。
滑动窗口示例(具体详细可参考:滑动窗口)

TCP传输效率与窗口大小有关:窗口越大,效率越高。(窗口无限大则TCP效率就与UDP一样,但是这样的话TCP的可靠性就无法保证了)
如果出现丢包/乱序怎么办?
① 传输的数据报丢了:应答ACK会一直索要未接收到的部分,几次之后主机A就会对丢失的数据报进行重传,没丢失的包不进行重传(没有任何重复的工作),而此时B补齐了空缺,接收到了所有已经传输过来的数据。–》快速重传(搭配滑动窗口机制的超时重传)
② 应答ACK丢了:没有任何影响,因为后面ACK到达就说明前面的所有都已经到达了。
但是不是说有了快速重传,超时重传就没有意义了:
① 当传输的数据很多的时候进行批量传输,此时就遵守快速重传方式;
② 但是如果传输的数据很少(如只有一条),那么此时仍然是按照超时重传的方式来进行的。

16位能表示的最大数就是64Kb,那么是否意味着滑动窗口最大就是64kb呢?
其实不是,在TCP报头的“选项”中会有一个特殊的值叫“窗口大小的扩展因子”,是可以通过扩展因子来表示更大的滑动窗口大小值的。
流量控制过程
① 窗口大小是动态变化的,每次ACK之后都会调整窗口大小
② 如果此时窗口大小变为0,也就是告诉发送方先别发送,但是如果主机A不进行数据发送,则B没法应答ACK,如果B不应答ACK,则后续缓冲区里有空闲空间时如何告知主机A呢?
主机A会发送一个探测报文,该报文长度只有1,不携带任何业务数据(不带载荷),只是探测一下窗口大小应该为多少,也就是为了B能够返回ACK来告知A其窗口大小。(探测报文是周期性发送,不是立即发送)
流量控制:是通过接收方的处理能力来衡量发送方的速率的。
以上所述只是考虑了接收方的处理速率,但是我们还是需要考虑中间这些转发节点的情况(类似于木桶原理)。接收方的速率容易量化,但是中间节点的情况难以量化。所以,如何考虑衡量中间节点的情况呢?
思路:把中间的这些设备视为一个“整体”,通过“做实验”的方式来验证发送速度多少合适,即从小的开始发送,进行“提速丢包则降速,降速畅通则提速”的循环,以达到“动态平衡”。(网络环境不是一成不变的)
也就是【拥塞控制】来衡量中间转发结点的处理速率。

当速率达到上限就会出现网络拥堵,从而出现丢包;此时窗口大小一下子会回到最初的值,重复刚才的指数增长+线性增长,并且要动态调整阈值,阈值调整为刚才丢包的窗口的一半。
注:TCP相关的机制还没有介绍完,详见下篇博客