TCP协议如何保证可靠传输

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP协议如何保证可靠传输相关的知识,希望对你有一定的参考价值。

参考技术A

所以 TCP 针对数据包丢失的情况,会用重传机制解决。

重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据,也就是我们常说的超时重传。

TCP 会在以下两种情况发生超时重传:

我们先来了解一下什么是 RTT(Round-Trip Time 往返时延),从下图我们就可以知道:
RTT 指的是数据发送时刻到接收到确认的时刻的差值,也就是包的往返时间。

上图中有两种超时时间不同的情况:

精确的测量超时时间 RTO 的值是非常重要的,这可让我们的重传机制更高效。
根据上述的两种情况,我们可以得知,超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。

如果超时重发的数据,再次超时的时候,又需要重传的时候,TCP 的策略是 超时间隔加倍。

也就是 每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。

超时触发重传存在的问题是,超时周期可能相对较长。那是不是可以有更快的方式呢?

于是就可以用「快速重传」机制来解决超时重发的时间等待。

TCP 还有另外一种快速重传(Fast Retransmit)机制,它不以时间为驱动,而是以数据驱动重传。

快速重传机制,是如何工作的呢?其实很简单,一图胜千言。

在上图,发送方发出了 1,2,3,4,5 份数据:

还有一种实现重传机制的方式叫:SACK( Selective Acknowledgment 选择性确认)。

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

如下图,发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有 200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。

Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。

下面举例两个栗子,来说明 D-SACK 的作用。

这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。

如果你说完一句话,我在处理其他事情,没有及时回复你,那你不是要干等着我做完其他事情后,我回复你,你才能说下一句话,很显然这不现实。

所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。

为解决这个问题,TCP 引入了窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。

那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。

窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。

假设窗口大小为 3 个 TCP 段,那么发送方就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以通过「下一个确认应答进行确认」。

TCP 头里有一个字段叫 Window,也就是窗口大小。

这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。

所以, 通常窗口的大小是由接收方的窗口大小来决定的

发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。

并不是完全相等,接收窗口的大小是 约等于 发送窗口的大小的。

因为滑动窗口并不是一成不变的。比如,当接收方的应用进程读取数据的速度非常快的话,这样的话接收窗口可以很快的就空缺出来。那么新的接收窗口大小,是通过 TCP 报文中的 Windows 字段来告诉发送方。那么这个传输过程是存在时延的,所以接收窗口和发送窗口是约等于的关系。

如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。

为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。

前面的流量控制例子,我们假定了发送窗口和接收窗口是不变的,但是实际上,发送窗口和接收窗口中所存放的字节数,都是放在操作系统内存缓冲区中的,而操作系统的缓冲区,会被操作系统调整。

可见最后窗口都收缩为 0 了,也就是发生了窗口关闭。当发送方可用窗口变为 0 时,发送方实际上会定时发送窗口探测报文,以便知道接收方的窗口是否发生了改变,这个内容后面会说,这里先简单提一下。

所以,如果发生了先减少缓存,再收缩窗口,就会出现丢包的现象。

为了防止这种情况发生,TCP 规定是不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存,这样就可以避免了丢包情况。

在前面我们都看到了,TCP 通过让接收方指明希望从发送方接收的数据大小(窗口大小)来进行流量控制。

这会导致发送方一直等待接收方的非 0 窗口通知,接收方也一直等待发送方的数据,如不采取措施,这种相互等待的过程,会造成了死锁的现象。

窗口探测的次数一般为 3 次,每次大约 30-60 秒(不同的实现可能会不一样)。如果 3 次过后接收窗口还是 0 的话,有的 TCP 实现就会发 RST 报文来中断连接。

一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。

在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大....

所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。

于是,就有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。

为了在「发送方」调节所要发送数据的量,定义了一个叫做「拥塞窗口」的概念。

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

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

慢启动的算法记住一个规则就行:当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。

这里假定拥塞窗口 cwnd 和发送窗口 swnd 相等,下面举个栗子:

连接建立完成后,一开始初始化 cwnd = 1,表示可以传一个 MSS 大小的数据。
当收到一个 ACK 确认应答后,cwnd 增加 1,于是一次能够发送 2 个
当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,所以这一次能够发送 4 个
当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以比之前多发 4 个,所以这一次能够发送 8 个。

可以看出慢启动算法,发包的个数是 指数性的增长

有一个叫慢启动门限 ssthresh (slow start threshold)状态变量。

前面说道,当拥塞窗口 cwnd 「超过」慢启动门限 ssthresh 就会进入拥塞避免算法。

一般来说 ssthresh 的大小是 65535 字节。

那么进入拥塞避免算法后,它的规则是:每当收到一个 ACK 时,cwnd 增加 1/cwnd。

接上前面的慢启动的栗子,现假定 ssthresh 为 8:

当 8 个 ACK 应答确认到来时,每个确认增加 1/8,8 个 ACK 确认 cwnd 一共增加 1,于是这一次能够发送 9 个 MSS 大小的数据,变成了线性增长。

所以,我们可以发现,拥塞避免算法就是将原本慢启动算法的指数增长变成了线性增长,还是增长阶段,但是增长速度缓慢了一些。

就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。

当触发了重传机制,也就进入了「拥塞发生算法」。

当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:

发生超时重传的拥塞发生算法

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

这个时候,ssthresh 和 cwnd 的值会发生变化:

还有更好的方式,前面我们讲过「快速重传算法」。当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。

TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则 ssthresh 和 cwnd 变化如下:

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

正如前面所说,进入快速恢复之前,cwnd 和 ssthresh 已被更新了:

网络协议趣谈TCP协议可靠性保证

很多时候都是在公网上传输数据,而公网往往是不可靠的,因而需要很多的机制去保证传输的可靠性,这里面需要恒心,也即各种重传的策略,还需要有智慧,也就是说这里面包含着大量的算法

一、如何做个靠谱的人

TCP想成为一个成熟稳重的人,成为一个靠谱的人。那一个人怎么样才算靠谱呢?

1.1 对于每件事情都有应答

工作中经常就有这样的场景,比如交代给下属一个事情以后,下属到底能不能做到,做到什么
程度,什么时候能够交付,往往就会有应答有回复。这样,处理事情的过程中一旦有异常,也可以尽快知道,而不是交代完之后就石沉大海,过了一个月再问他说不记得了

对应到网络协议上,就是客户端每发送的一个包,服务器端都应该有个回复,如果服务器端超过一定的时间没有回复,客户端就会重新发送这个包,直到有回复

这个发送应答的过程是什么样呢?可以是上一个收到了应答,再发送下一个。这种模式有点像两个人直接打电话,你一句,我一句

1.2 根据事情ID并行交代和应答

但是这种方式的缺点是效率比较低,如果一方在电话那头处理的时间比较长,这一头就要干等着,双方都没办法干其他事情。在日常工作中也不是这样的,不能交代你的下属办一件事情就一直打着电话看着他做,而是应该他按照你的安排先将事情记录下来,办完一件回复一件。在他办事情的过程中,你还可以同时交代新的事情,这样双方就并行了

如果使用这种模式,其实需要你和你的下属就不能靠脑子了,而是要都准备一个本子,你每
交代下属一个事情,双方的本子都要记录一下

当你的下属做完一件事情,就回复你做完了,你就在你的本子上将这个事情划去。同时你的本子上每件事情都有时限,如果超过了时限下属还没有回复,你就要主动重新交代一下:上次那件事情,你还没回复我,咋样啦?

既然多件事情可以一起处理,那就需要给每个事情编个号,防止弄错了。例如,程序员平时看任务的时候,都会看JIRA的ID,而不是每次都要描述一下具体的事情
在大部分情况下,对于事情的处理是按照顺序来的,先来的先处理,这就给应答和汇报工作带来了方便。等开周会的时候,每个程序员都可以将JIRA ID的列表拉出来,说以上的都做完了,而不用一个个说

二、如何实现一个靠谱的协议

2.1 累计确认/应答

TCP协议使用的也是同样的模式
为了保证顺序性,每一个包都有一个ID。在建立连接的时候会商定起始的ID是什么,然后按照ID一个个发送。为了保证不丢包,对于发送的包都要进行应答,但是这个应答也不是一个一个来的,而是会应答某个之前的ID表示都收到了,这种模式称为累计确认或者累计应答(cumulative acknowledgment)

2.2 发送端缓存

为了记录所有发送的包和接收的包,TCP也需要发送端和接收端分别都有缓存来保存这些记 录

2.2.1 发送端缓存的数据内容

发送端的缓存里是按照包的ID一个个排列,根据处理的情况分成四个部分

  • 第一部分:发送了并且已经确认的
    这部分就是你交代下属并且也做完了的,应该划掉

  • 第二部分:发送了并且尚未确认的
    这部分是你交代下属但是还没做完的,需要等待做完的回复之后才能划掉

  • 第三部分:没有发送但是已经等待发送的
    这部分是你还没有交代给下属,但是马上就要交代的

  • 第四部分:没有发送并且暂时还不会发送的
    这部分是你还没有交代给下属,而且暂时还不会交代给下属的

这里面为什么要区分第三部分和第四部分呢?没交代的一下子全交代了不就完了吗?

这就是流量控制,把握分寸。作为项目管理人员,应该根据以往的工作情况和这个员工反馈的能力、抗压力等,先在心中估测一下这个人一天能做多少工作。如果工作布置少了就会不饱和,如果工作布置多了他就会做不完,如果使劲逼迫人家可能就要辞职

2.2.2 Advertised window

到底一个员工能够同时处理多少事情呢?
在TCP里,接收端会给发送端报一个窗口的大小, 叫Advertised window。这个窗口的大小应该等于上面的第二部分加上第三部分,就是已经交代了没做完的加上马上要交代的。超过这个窗口的接收端做不过来,就不能发送了

2.2.3 发送端保持的数据结构

于是,发送端需要保持下面的数据结构


LastByteAcked:第一部分和第二部分的分界线
LastByteSent:第二部分和第三部分的分界线
LastByteAcked + AdvertisedWindow:第三部分和第四部分的分界线

2.3 接收端缓存

2.3.1 接收端缓存的数据内容

对于接收端来讲,它的缓存里记录的内容要简单一些

  • 第一部分:接受并且确认过的
    这部分是领导交代给我,并且已经做完的

  • 第二部分:还没接收但是马上就能接收的
    这部分是自己能够接受的最大工作量

  • 第三部分:还没接收也没法接收的
    也即超过工作量的部分,实在做不完

2.3.2 接收端保持的数据结构

对应的数据结构就像这样


MaxRcvBuffer:最大缓存的量
LastByteRead:已经接收了,但是还没被应用层读取的
NextByteExpected:第一部分和第二部分的分界线

2.3.3 AdvertisedWindow大小

第二部分的窗口有多大呢?
NextByteExpected和LastByteRead的差其实是还没被应用层读取的部分占用掉的 MaxRcvBuffer的量,定义为A

AdvertisedWindow其实是MaxRcvBuffer减去A

也就是:AdvertisedWindow=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead)

那第二部分和第三部分的分界线在哪里呢?NextByteExpected加AdvertisedWindow就是第二部分和第三部分的分界线,其实也就是LastByteRead加上MaxRcvBuffer

其中第二部分里面,由于受到的包可能不是顺序的,会出现空挡,只有和第一部分连续的,可以马上进行回复,中间空着的部分需要等待,哪怕后面的已经来了

三、顺序问题与丢包问题

3.1 顺序和丢包问题出现的例子

接下来结合一个例子来看

还是刚才的图,在发送端来看,1、2、3已经发送并确认,4、5、6、7、8、9都是发送了还没确认,10、11、12是还没发出的,13、14、15是接收方没有空间不准备发的

在接收端来看,1、2、3、4、5是已经完成ACK但没读取的,6、7是等待接收的,8、9是已经接收但是没有ACK的

发送端和接收端当前的状态如下:

1、2、3没有问题,双方达成了一致
4、5接收方说ACK了,但是发送方还没收到,有可能丢了,也有可能在路上
6、7、8、9肯定都发了,8、9已经到了,6、7还没到,出现了乱序,缓存着但是没办法ACK

根据这个例子,可以知道顺序问题和丢包问题都有可能发生,所以先来看确认与重发的机制

假设4的确认到了,不幸的是5的ACK丢了,6、7的数据包丢了,这该怎么办呢?

3.2 超时重试时间大小问题

一种方法就是超时重试,即对每一个发送了但是没有ACK的包都有设一个定时器,超过了一定的时间就重新尝试。但是这个超时的时间如何评估呢?这个时间不宜过短,时间必须大于往返时间RTT,否则会引起不必要的重传。也不宜过长,这样超时时间变长,访问就变慢了

3.3 自适应重传

估计往返时间,需要TCP通过采样RTT的时间,然后进行加权平均算出一个值,而且这个值还是要不断变化的,因为网络状况不断的变化。除了采样RTT,还要采样RTT的波动范围,计算出一个估计的超时时间。由于重传时间是不断变化的,所以称为自适应重传算法(Adaptive Retransmission Algorithm)

3.4 超时间隔加倍

如果过一段时间,5、6、7都超时了,就会重新发送。接收方发现5原来接收过,于是丢弃 5,6收到了,发送ACK,要求下一个是7,7不幸又丢了。当7再次超时需要重传时,TCP的策略是超时间隔加倍。每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,说明网络环境差,不宜频繁反复发送

3.5 快速重传机制

超时触发重传存在的问题是,超时周期可能相对较长。那是不是可以有更快的方式呢?

有一个可以快速重传的机制,当接收方收到一个序号大于下一个所期望的报文段时,就检测到数据流中的一个间格,于是发送三个冗余的ACK,客户端收到后,就在定时器过期之前重传丢失的报文段
例如,接收方发现6、8、9都已经接收了,就是7没来,那肯定是丢了,于是发送三个6的ACK要求下一个是7。客户端收到3个就会发现7的确又丢了,不等超时马上重发

3.6 SACK

还有一种方式称为Selective Acknowledgment(SACK)
这种方式需要在TCP头里加一个SACK的东西,可以将缓存的地图发送给发送方。例如可以发送ACK6、SACK8、SACK9, 有了地图发送方一下子就能看出来是7丢了

四、流量控制问题

再来看流量控制机制,在对于包的确认中同时会携带一个窗口的大小

先假设窗口不变的情况,窗口始终为9。4的确认来的时候会右移一个,这个时候第13个包也可以发送了


这时,假设发送端发送过猛,会将第三部分的10、11、12、13全部发送完毕,之后就停止发送,未发送可发送部分为0


当对于包5的确认到达的时候,在客户端相当于窗口再滑动了一格,这时才可以有更多的包可以发送,例如第14个包才可以发送


如果接收方实在处理的太慢导致缓存中没有空间了,可以通过确认信息修改窗口的大小,甚至可以设置为0,则发送方将暂时停止发送

假设一个极端情况,接收端的应用一直不读取缓存中的数据,当数据包6确认后窗口大小就不能再是9了,缩小一个变为8

这个新的窗口8通过6的确认消息到达发送端时,此时窗口没有平行右移,而是仅仅左面的边右移了,窗口的大小从9改成了8


如果接收端还是一直不处理数据,则随着确认的包越来越多,窗口越来越小,直到为0


当这个窗口通过包14的确认到达发送端的时候,发送端的窗口也调整为0,停止发送


如果这样的话,发送方会定时发送窗口探测数据包,看是否有机会调整窗口的大小。当接收方比较慢的时候,要防止低能窗口综合征,别空出一个字节来就赶快告诉发送方,然后马上又填满了,可以当窗口太小时不更新窗口,直到达到一定大小或者缓冲区一半为空,才更新窗口

这就是常说的流量控制

五、拥塞控制问题

5.1 拥塞窗口和滑动窗口

最后,看一下拥塞控制的问题,也是通过窗口的大小来控制的,前面的滑动窗口rwnd是怕发送方把接收方缓存塞满,而拥塞窗口cwnd是怕把网络塞满

这里有一个公式LastByteSent - LastByteAcked <= min {cwnd, rwnd},是拥塞窗口和滑动窗口共同控制发送的速度

5.2 如何判断网络是否满

那发送方怎么判断网络是不是满呢?这其实是个挺难的事情,因为对于TCP协议来讲压根不知道整个网络路径都会经历什么,对他来讲就是一个黑盒
TCP发送包常被比喻为往一个水管里面灌水,而TCP的拥塞控制就是在不堵塞,不丢包的情况下尽量发挥带宽

水管有粗细,网络有带宽,也即每秒钟能够发送多少数据,水管有长度,端到端有时延。在理想状态下,水管里面水的量=水管粗细 x 水管长度。对于到网络上,通道的容量 = 带宽 × 往返延迟

如果设置发送窗口使得发送但未确认的包为为通道的容量,就能够撑满整个管道

如图所示,假设往返时间为8s,去4s,回4s,每秒发送一个包,每个包1024byte。已经过去了8s则8个包都发出去了,其中前4个包已经到达接收端,但是ACK还没有返回,不能算发送成功。5-8后四个包在路上还没被接收。这时整个管道正好撑满,在发送端已发送未确认的为8个包,正好等于带宽,也即每秒发送1个包乘以来回时间8s

5.3 超过通道容量时可能的问题

如果在这个基础上再调大窗口,使得单位时间内更多的包可以发送,会出现什么现象呢?

想象一下,原来发送一个包从一端到达另一端,假设一共经过四个设备,每个设备处理一个包时间耗费1s,所以到达另一端需要耗费4s,如果发送的更加快速则单位时间内,会有更多的包到达这些中间设备,这些设备还是只能每秒处理一个包的话,多出来的包就会被丢弃,这是并不想看到的情况

这个时候可以想其他的办法,例如这个四个设备本来每秒处理一个包,但是在这些设备上加缓存,处理不过来的在队列里面排着,这样包就不会丢失,但是缺点是会增加时延,这个缓存的包4s肯定到达不了接收端了,如果时延达到一定程度就会超时重传,也是不想看到的情况

5.4 怎么判断窗口调整的大小

于是TCP的拥塞控制主要来避免两种现象,包丢失和超时重传。一旦出现了这些现象就说明发送速度太快了,要慢一点。但是一开始怎么知道速度多快呢,怎么知道应该把窗口调整到多大呢?

5.4.1 慢启动

如果通过漏斗往瓶子里灌水,就知道不能一桶水一下子倒进去,肯定会溅出来,要一开始慢慢的倒,然后发现总能够倒进去时可以越倒越快,这叫作慢启动

5.4.2 指数性增长

一条TCP连接开始:
cwnd设置为一个报文段,一次只能发送一个
当收到这一个确认时cwnd加一,于是一次能够发送两个
当这两个的确认到来的时候,每个确认cwnd加一,两个确认cwnd加二,于是一次能够发送四个
当这四个的确认到来的时候,每个确认cwnd加一,四个确认cwnd加四,于是一次能够发送八个

可以看出这是指数性的增长

涨到什么时候是个头呢?有一个值ssthresh为65535个字节,当超过这个值时就要小心一点了,不能倒这么快了,可能快满了要慢下来

5.4.3 线性增长

每收到一个确认后cwnd增加1/cwnd,接着上面的过程一次发送八个,当八个确认到来时每个确认增加1/8,八个确认一共cwnd增加1,于是一次能够发送九个,变成了线性增长

5.4.4 拥塞导致网络卡顿

但是线性增长还是增长,还是越来越多,直到有一天水满则溢,出现了拥塞,这时候一般就会一下子降低倒水的速度,等待溢出的水慢慢渗下去

拥塞的一种表现形式是丢包,需要超时重传,这时将sshresh设为cwnd/2,将cwnd设为1,重新开始慢启动。这真是一旦超时重传马上回到解放前,这种方式太激进了,将一个高速的传输速度一下子停了下来,会造成网络卡顿

5.4.5 快速重传算法处理

前面讲过快速重传算法。当接收端发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速的重传,不必等待超时再重传。TCP认为这种情况不严重,因为大部分没丢,只丢了一小部分,cwnd减半为cwnd/2,然后sshthresh = cwnd,当三个包返回时cwnd = sshthresh + 3,也就是没有一夜回到解放前,而是还在比较高的值呈线性增长

5.5 TCP拥塞控制的问题

就像前面说的一样,正是这种知进退使得时延很重要的情况下,反而降低了速度。但是如果仔细想一下,TCP的拥塞控制主要来避免的两个现象都是有问题的

  • 第一个问题

丢包并不代表着通道满了,也可能是管子本来就漏水
例如公网上带宽不满也会丢包,这个时候认为拥塞了,退缩了,其实是不对的

  • 第二个问题

TCP的拥塞控制要等到将中间设备都填充满了,才发生丢包,从而降低速度,这时候已经晚了
其实TCP只要填满管道就可以了,不应该接着填,直到连缓存也填满

5.6 TCP BBR拥塞算法

为了优化这两个问题,后来有了TCP BBR拥塞算法
它企图找到一个平衡点,就是通过不断的加快发送速度将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡点可以很好的达到高带宽和低时延的平衡

六、小结

关于以上TCP协议可靠性保证的学习总结一下:

  • 顺序问题、丢包问题、流量控制都是通过滑动窗口来解决的,这其实就相当于领导和你
    的工作备忘录,布置过的工作要有编号,干完了有反馈,活不能派太多,也不能太少

  • 拥塞控制是通过拥塞窗口来解决的,相当于往管道里面倒水,快了容易溢出,慢了浪费带 宽,要摸着石头过河,找到最优值

以上是关于TCP协议如何保证可靠传输的主要内容,如果未能解决你的问题,请参考以下文章

Tcp协议保证可靠传输机制

Tcp协议保证可靠传输机制

TCP协议如何保证数据可靠性

TCP是如何实现可靠传输的?

TCP 协议如何保证可靠传输

一文弄懂TCP协议如何保证数据传输的可靠性