川渝携手设立经济创新发展基金
06-18
我们刚开始学习网络编程的时候,都接触过TCP。 TCP中,有多种数据传输策略,例如滑动窗口、拥塞窗口机制、慢启动、快恢复、拥塞避免等。
通过本文,我们将了解TCP中如何使用滑动窗口。滑动窗口实现TCP流量控制。
首先明确一下滑动窗口的范围:TCP是双工协议,会话双方可以同时接收和发送数据。会话双方维护一个发送窗口和一个接收窗口。
各自的接收窗口大小取决于应用程序、系统和硬件限制(TCP 传输速率不能大于应用程序的数据处理速率)。各自的发送窗口要求取决于对端通告的接收窗口,并且要求是相同的。
滑动窗口解决的是流量控制的问题,即如果接收端和发送端以不同的速度处理数据包,如何使双方达成一致。接收端的缓存将数据传输到应用层,但这个过程不一定是瞬时的。
如果发送速度太快,接收端就会发生数据溢出。流量控制解决了这个问题。
上图的发送者窗口是发送者滑动窗口的简化图。我们可以将数据分为4部分:已发送和已确认的字节(蓝色部分)已发送但尚未确认的字节(黄色部分)未发送的字节和接收方准备接收的字节,即在缓冲区buffer中的字节(尚未发送且接收方未准备好接收的数据已经在缓冲区中,但这部分数据尚未被处理(灰色部分)。
第三部分,即绿色部分,也称为可用窗口,因为这是发送者可用的窗口。发送窗口由黄色和绿色部分组成。
这些字节要么已发送,要么可以发送。当发送方发送21-25个字节并使用可用窗口中的所有字节时,可用窗口可能为空,而发送窗口保持不变(如下所示)。
当发送方收到字节16-19的ACK时,发送窗口向右滑动4个字节。更新后的可用窗口可用于队列中的以下字节(如下图所示)。
为了方便理解,我们以后将使用窗口名称的缩写,即:SND.WND,代表发送窗口。 SND.UNA,表示发送未确认指针,指向发送窗口的第一个字节。
SND.NXT,表示Send Next指针,指向可用窗口第一个字节的缩写后,如下图所示: 根据这些定义,我们可以用一个公式来表示可用窗口大小。代码语言:javascript copy 可用窗口(available window)大小 = SND.UNA + SND.WND - SND.NXT 接收方窗口 共有三种接收窗口: 1. 已接收并已向发送方发送确认 ACK 2. 尚未接收但允许发送方发送数据意味着接收窗口可用。
3、尚未接收,发送端不允许发送数据,即已经在缓冲区中但尚未处理。第二种称为接收窗口,也称为RCV.WND。
与发送窗口类似,指针RCV.NXT代表接收下一个指针,指向接收窗口的第一个字节。接收窗口不是静态的。
如果服务器性能高,读取数据快,接收窗口可能会扩大。否则,它可能会缩小。
接收方通过在 TCP 段标头中的窗口字段中指示大小来传达其接收窗口。当发送者收到它时,这个窗口大小就成为可用窗口。
发送和接收数据需要时间。因此,接收窗口不等于特定时刻的可用窗口。
下面,为了更好地理解TCP中滑动窗口的使用,我们将用一个简单的例子来模拟一下。示例(相同大小) 我们模拟请求和响应,以更好地理解滑动窗口的工作原理。
为了简化模拟,我们尽可能地简化过程,例如:我们忽略最大段大小(MSS)。 MSS 根据所选的网络路由而变化。
使接收窗口等于可用窗口,并且在此过程中两者保持不变。在上面的示例中,有 10 个步骤。
客户端请求资源,服务器响应分为三部分: 1. 50 字节的标头 2. 80 字节的数据 13. 一个字节的数据 2. 各方可以同时作为发送方和接收方。我们假设客户端的发送窗口(SND.WND)是字节,接收窗口(RCV.WND)是字节。
因此,服务器的SND.WND 是字节,RCV.WND 是字节。上图中客户端的初始状态。
我们假设它之前已从服务器接收过字节,因此 RCV.NXT 指向这一点。由于还没有发送任何东西,所以 SND.UNA 和 SND.NXT 都指向 1。
代码语言:javascript 复制可用窗口(available window)大小 = SND.UNA + SND.WND - SND.NXT 根据这个公式,客户端的可用窗口大小为 1 + - 1 =。这是服务器的起始状态,镜像另一端的状态是客户端。
因为它已经发送了字节,所以SND.UNA和SND.NXT都指向。 RCV.NXT 指向 1,因为客户端尚未发送任何请求。
服务器的可用窗口为+ - =。现在,我们从第一步开始:客户端发送第一个字节请求。
就在这时,窗口发生了变化。该字节已发送,但尚未收到 ACK。
因此,SND.NXT 向右滑动字节。其他指针保持不变。
可用窗口变为 1 + - = 。在第2步中,我们的焦点转移到服务器上,从服务器的角度进行分析。
当服务器收到请求时,RCV.NXT 向右滑动字节。然后它发送 50 字节的 ACK 回复。
50字节的确认ACK已发送给发送方即客户端,但尚未收到回复ACK,因此SND.NXT右移50字节。 SND.UNA 没有动。
可用窗口大小变为+ - =。现在让我们转向客户端。
当收到 50 字节回复时,RCV.NXT 向右移动 50 字节。 SND.UNA 在收到先前发送字节的 ACK 后向右滑动。
SND.NXT 保持不变,因为客户端没有发送任何数据。可用窗口更改为 + - =。
再次转移到服务器端。可用窗口为字节。
服务器可以发送 80 字节的段。 SND.NXT 右滑 80 字节。
SND.UNA 保持不变,因为最后 50 个字节尚未得到确认。 RCV.NXT 保持不变,因为服务器没有收到任何数据。
可用窗口变为+ - = 20。客户端收到数据的第一部分并立即发送ACK。
当客户端收到80字节数据时,RCV.NXT右移。其他部分保持不变。
可用窗口大小保持不变。此时,服务器收到步骤 2 的 ACK,同时发送 50 字节的回复。
SND.UNA 右移 50 个字节。其他部分保持不变。
可用窗口大小变为 + - = 70。当服务器发送数据 1(80 字节部分)时,再次收到步骤 4 中的另一个 ACK??。
SND.UNA 右移 80 个字节。其他部分保持不变。
可用窗口大小变为+ - =。步骤8,服务器数据2,大小为字节。
SND.NXT 向右移动字节。其他部分保持不变。
可用窗口大小变为 + - = 50。继续到客户端。
当客户端接收到字节时,RCV.NXT 右移字节。其他部分保持不变。
可用窗口大小保持不变。最后,服务器收到先前响应的 ACK。
SND.UNA 向右移动字节。其他部分保持不变。
可用窗口大小变为+ - =。至此,滑动窗口不变的例子就解释完了,那么滑动窗口大小变化呢? TCP中是如何实现的?示例(大小不同的窗口) 在前面的示例中,我们假设发送和接收窗口保持不变。
这个假设本身在实践中是无效的,因为它不存在。两个窗口中的字节都存在于操作系统缓冲区中并且可以调整。
例如,当我们的应用程序读取字节的速度不够快时,缓冲区中的可用空间就会缩小。让我们介绍一下本例中的窗口更改,看看它如何影响可用窗口。
我们简化了这种情况,将可用窗口集中在客户端上。在此示例中,客户端始终是发送者,服务器是接收者。
当服务器发送 ACK 时,它还包含更新的窗口大小。最初,客户端发送请求的第一个字节。
该字节已发送,但 ACK 尚未发送。可用窗口缩小为字节。
发送窗口保持在字节。当服务器收到请求时,应用程序读取前 50 个字节,并且缓冲区中仍有字节,占用接收窗口中的可用空间字节。
因此,接收窗口缩小为字节。接下来,服务器发送带有更新的字节接收窗口的 ACK。
客户端收到 ACK 并将其发送窗口大小更新为 。此时,可用窗口与发送窗口相同,因为所有字节都已被确认。
客户端使用可用窗口中的所有可用空间再次发送另一个字节请求。服务器接收到字节后,应用程序仍然运行缓慢,总共只读取了 70 个字节,并在缓冲区中留下了字节。
这导致接收窗口再次缩小。现在,我们减少到 20 字节。
在 ACK 消息中,服务器与客户端共享更新的窗口大小。同样,客户端在收到 ACK 后将其发送窗口更新为 20 字节。
可用窗口也变为 20 字节。在这种情况下,客户端将停止发送任何大于 20 字节的请求,直到收到以下消息中的另一个窗口更新。
如果服务器不再有消息,我们是否会继续使用 20 字节的可用窗口?我们不会。为了避免这种情况,客户端的 TCP 定期检测窗口大小。
一旦释放了更多空间,可用窗口就会扩大,并且可以发送更多数据。结论 可用窗口的计算是理解TCP滑动窗口的关键。
为了学习可用窗口的计算,我们需要了解3个指针——SND.UNA、SND.NXT和RCV.NXT。假设窗口大小永远不会改变有助于我们理解进度。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-18
06-18
06-17
06-18
06-18
06-18
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用