即使报文正常的传输到对端,也可能出现在传输过程中报文出错的问题 。这时候对端会抛弃该报文并等待 A 端重传 。一般定时器设定的时间都会大于一个 RTT 的平均时间 。
ACK 超时或丢失
【工程师进阶:深入TCP协议】对端传输的应答也可能出现丢失或超时的情况 。那么超过定时器时间 A 端照样会重传报文 。这时候 B 端收到相同序号的报文会丢弃该报文并重传应答,直到 A 端发送下一个序号的报文 。
在超时的情况下也可能出现应答很迟到达,这时 A 端会判断该序号是否已经接收过,如果接收过只需要丢弃应答即可 。
从上面的描述中大家肯定可以发现这肯定不是一个高效的方式 。假设在良好的网络环境中,每次发送数据都需要等待片刻肯定是不能接受的 。那么既然我们不能接受这个不那么高效的协议,就来继续学习相对高效的协议吧 。
连续 ARQ
在连续 ARQ 中,发送端拥有一个发送窗口,可以在没有收到应答的情况下持续发送窗口内的数据,这样相比停止等待 ARQ 协议来说减少了等待时间,提高了效率 。
累计确认
连续 ARQ 中,接收端会持续不断收到报文 。如果和停止等待 ARQ 中接收一个报文就发送一个应答一样,就太浪费资源了 。通过累计确认,可以在收到多个报文以后统一回复一个应答报文 。报文中的 ACK 标志位可以用来告诉发送端这个序号之前的数据已经全部接收到了,下次请发送这个序号后的数据 。
但是累计确认也有一个弊端 。在连续接收报文时,可能会遇到接收到序号 5 的报文后,并未接收到序号 6 的报文,然而序号 7 以后的报文已经接收 。遇到这种情况时,ACK 只能回复 6,这样就会造成发送端重复发送数据的情况 。
滑动窗口在ARQ协议中,发送端有一个发送窗口 。在 TCP 中,两端其实都维护着窗口:分别为发送端窗口和接收端窗口 。
发送端窗口包含已发送但未收到应答的数据和可以发送但是未发送的数据 。

文章插图
发送端窗口是由接收窗口剩余大小决定的 。接收方会把当前接收窗口的剩余大小写入应答报文,发送端收到应答后根据该值和当前网络拥塞情况设置发送窗口的大小,所以发送窗口的大小是不断变化的 。
当发送端接收到应答报文后,会随之将窗口进行滑动

文章插图
滑动窗口是一个很重要的概念,它帮助 TCP 实现了流量控制的功能 。接收方通过报文告知发送方还可以发送多少数据,从而保证接收方能够来得及接收数据,防止出现接收方带宽已满,但是发送方还一直发送数据的情况 。
Zero 窗口
在发送报文的过程中,可能会遇到对端出现零窗口的情况 。在该情况下,发送端会停止发送数据,并启动 persistent timer。该定时器会定时发送请求给对端,让对端告知窗口大小 。在重试次数超过一定次数后,可能会中断 TCP 链接 。
拥塞处理
拥塞处理和流量控制不同,后者是作用于接收方,保证接收方来得及接受数据 。而前者是作用于网络,防止过多的数据拥塞网络,避免出现网络负载过大的情况 。
拥塞处理包括了四个算法,分别为:慢开始,拥塞避免,快速重传,快速恢复 。
慢开始算法
慢开始算法,顾名思义,就是在传输开始时将发送窗口慢慢指数级扩大,从而避免一开始就传输大量数据导致网络拥塞 。想必大家都下载过资源,每当我们开始下载的时候都会发现下载速度是慢慢提升的,而不是一蹴而就直接拉满带宽 。
慢开始算法步骤具体如下
- 连接初始设置拥塞窗口(Congestion Window) 为 1 MSS(一个分段的最大数据量)
- 每过一个 RTT 就将窗口大小乘二
- 指数级增长肯定不能没有限制的,所以有一个阈值限制,当窗口大小大于阈值时就会启动拥塞避免算法 。
拥塞避免算法相比简单点,每过一个 RTT 窗口大小只加一,这样能够避免指数级增长导致网络拥塞,慢慢将大小调整到最佳值 。
在传输过程中可能定时器超时的情况,这时候 TCP 会认为网络拥塞了,会马上进行以下步骤:
- 将阈值设为当前拥塞窗口的一半
- 将拥塞窗口设为 1 MSS
- 启动拥塞避免算法
快速重传一般和快恢复一起出现 。一旦接收端收到的报文出现失序的情况,接收端只会回复最后一个顺序正确的报文序号 。如果发送端收到三个重复的 ACK,无需等待定时器超时而是直接启动快速重传算法 。具体算法分为两种:
推荐阅读
- 黑客术语介绍!web渗透小白的进阶之路
- Linux 进阶语句
- linux进程间通信——深入理解linux信号量
- 每个架构师都在研究的康威定律,程序员进阶路上,你思考过吗?
- 工程师开发了一种全新的量子计算架构
- MySQL进阶篇 | 合理的使用索引结构和查询
- 纳粹月球基地 纳粹德国月球基地
- 范振钰|钓鱼大师的饵料值得信服吗?进阶换饵鱼不认,为何蓝鲫有靠谱标签
- 30名工程师,历时1300天打造,又一“国产”AI框架开源了
- MySQL innodb引擎深入讲解
