我目前正在学习 TCP,尤其是接收窗口方面。我已经从多个来源阅读了相关内容,有些内容我想确保自己理解。
据我了解,接收者公布了一个“接收窗口”,也就是——这也是我感到困惑的地方——发送方被允许在未经确认的情况下发送的字节数,换句话说,飞行中的数据。
现在,如果我尝试思考一下,我们在流量控制中的主要目标是确保发送方不会发送超过接收方可以处理的数据,即,我们要防止出现发送方发送数据而接收方必须丢弃的数据的情况,因为它没有地方存储它!
按照这个逻辑,我相信接收窗口应该与接收缓冲区的大小相对应(不知道是否完全相同,但窗口大小应该是接收缓冲区的派生词),我们限制接收窗口的原因是飞行中的数据发送方发送的问题是 - 如果发送方发送的数据超过窗口大小(这也是接收缓冲区的派生词),而接收方还没有确认某些数据(更新窗口大小),那么可能会出现接收端无法跟上的情况 - 即,它获取数据的速度比使用它的应用程序处理数据的速度快,从而导致段被丢弃(希望这清楚)。
但是,阅读这个帖子,@DavidShwartz 说,传输数据的目的不是为了避免缓冲区过满,而是为了处理通信通道引入的延迟. 我不太明白。
问题在于,谈论这个主题的每一个来源都没有解释流量控制的总体目标与飞行中的数据。
有人可以详细解释一下吗?
答案1
它同时做到了这两点。
接收窗口受可用缓冲区空间的限制,但对于大多数接收器来说这并不是什么大问题。
接收窗口的另一个重要功能是及时扩展传输,使其不出现十个连续数据包的突发,随后是静默,直到所有这些数据都被确认,然后再出现另一次突发。
相反,一种称为“TCP 慢启动”的机制将在数据传输过程中逐渐增加接收窗口,这样长时间运行的传输最终会得到间隔大致相等的数据包流,并且数据包的确认会在窗口末尾的下一个数据包必须发出时及时到达。
一旦建立了该流程,窗口将进一步增加,以允许替换丢失的数据包而不会停滞。
如果窗口大小线性增长直到达到传输中未确认的数据量(即传输延迟乘以传输速度),则可以实现良好的流程。
之所以不能仅通过确认来解决此问题,是因为突发的数据包很可能会在途中被丢弃(丢弃数据包是网络指示拥塞的方式),因此连接启动会更加不稳定,最终才能收敛到稳定的流量。
如果接收缓冲区小于正在传输的未确认数据量,则接收窗口将达到上限,流量将不均匀,除非接收堆栈通过延迟确认来弥补这一点——但这是一种不典型的情况。
答案2
飞行中的数据是一个通用术语,用于指已发送但尚未确认的数据。因为从发送者的角度来看,这些数据位于网络中的某个位置。发送方窗口是可传输的数据量,即发送方在接收到窗口第一段的 ACK 之前可以发送的数据量。
我认为,链接帖子中所说的,对于为什么在飞行过程中有一个窗口(即几个包裹),而不是只有一个。
尝试想象一下如果你只发送一个数据包然后等待 ACK 会发生什么,并将其与如果你一次发送 10 个数据包然后等待 ACK 会发生什么进行比较。计算数据传输速率是一个非常常见的考试任务。你会看到,如果发送方和接收方之间的延迟非常小(例如,它们在物理上很接近,就像在同一栋建筑中一样),一次发送一个数据包就可以了。如果延迟有点大,一次发送一个数据包是非常低效的。
- 现在,如果发送方只是发送数据包,而不考虑网络中的其他参与者,那么这些数据包很有可能被丢弃,从而浪费资源(在发送方、在网络中,可能在接收方)。因此,TCP 的发送方窗口是可变的,并且取决于两个机制:流量控制和拥塞控制。
流量控制就是你所描述的那样。它的目标是不让接收方过载。因此,接收方只需告诉发送方它可以接受多少数据。这称为接收窗口(与发送方窗口不同)。确切地说,它是操作系统接收缓冲区中的空间。应用程序在这里被间接合并,因为如果应用程序不从接收缓冲区获取数据,就不会释放空间。
拥塞控制是为了确保发送方不会使网络过载。这是一个大而复杂的话题。然而,另一个答案中描述的是拥塞控制,它与接收方窗口无关。有一个所谓的拥塞窗口,它估计(或应该估计)网络在不过载(即丢弃数据包)的情况下可以传输多少数据。
发送方窗口是接收方窗口和拥塞窗口的最小值,以便发送方不会使接收方或网络超载。