理解TCP协议中的滑动窗口
理解TCP协议的滑动窗口原理
什么是TCP协议的滑动窗口
首先,先看一下TCP协议在TCP/IP五层模型中的位置。
众所周知,TCP协议是一个基于字节流的传输层协议,它位于应用层之下和网络层之上,它提供了可靠的机制,能保证数据有序、可靠地到达对方系统。TCP连接首先会经过三次握手,三次握手成功之后连接就建立起来。此时发送方会将数据发送给接收方,接收方的系统内核接收到数据之后,一般会先将数据放到系统缓冲区中,直到系统发生中断后再处理。
在网络传输过程中,IP头部占用了20字节,TCP头部占用了20字节,换言之,每一次传输TCP报文都会有40字节的固定消耗。因此通信双方总是倾向于发送尽可能大的报文以提高网络效率。
由于通信双方处理数据的性能有所差异,如果接收到的数据大于自己的处理能力,就会引起问题。为了避免对方无限量地推送信息过来,在数据传输的过程中要进行流量控制,接收方在接收数据后,会发送ACK确认,此时就需要告知对方自己能够一次最多处理的字节数,以便对方能按照自己设定的数据大小来传输数据,这就是【滑动窗口】。
滑动窗口在TCP头部的表示
我们复习一下TCP头部的结构。
红框中表示的就是滑动窗口在TCP报文中的位置,滑动窗口是跟着ACK一起的,因此ACK的Flag置为1,同时指定窗口大小。可以看到,滑动窗口的范围是通过16个bit来表达,也就是从0到2的16次方,即接收端最多可以提供65535个字节的缓冲。滑动窗口的值会随着系统的资源和处理能力动态变化。
使用wireshark抓取TCP报文查看滑动窗口的实际值
这里使用wireshark抓取baidu.com的TCP报文。可以看到,No.36是本机对服务器之前发送数据(No.31)的一个ACK确认(ACK的Flag标记成1),同时声明窗口大小(window size)为1040。
紧接着是No.37对No.30发送一个ACK确认,受系统进程资源的影响,这时窗口的大小动态调整为948。
滑动窗口的简单例子
假设通信双方建立了一条TCP连接,我们就可以对某一时刻的数据进行快照,这时我们的发送方的窗口可以分为以下四部分:
如图所示,发送方的窗口快照可以将窗口分为四个部分:
Category 1:已发送且已收到ACK确认的部分:1-31字节
Category 2:已发送但未收到ACK确认的部分:32-45字节
Category 3:未发送且在接收方范围内的部分:46-51字节(这部分数据仍在对方系统处理能力之内)
Category 4:未发送但数据大小超过对方系统处理范围之外的部分:52以后的字节
发送窗口与可用窗口
我们可以对这个窗口模型进一步划分,分为【发送窗口】和【可用窗口】,如图所示
Category 3意味着如果我们需要继续发信息,46-51字节是能够发送的,我们称为【可用窗口】(Usable Window)。而Category2 + Category3的部分(32-51字节),我们称为【发送窗口】(Send Window)。
当46-51字节发送完毕后,且如果还没接收到对方的ACK,这时【可用窗口】就会耗尽,即【可用窗口】为0,窗口关闭,不能再继续发送。
发送窗口的移动
假设这时32-36字节得到了对方的ACK确认,如图所示
在【发送窗口不变】的前提下,窗口会往后移动5个字节,这时52-56字节将变为【可用窗口】,此时又可以继续发送数据。这就是滑动窗口名字的来源。
后记
TCP的滑动窗口机制,能够有效地对发送和接收双方实现流量控制。当然,流量控制除了滑动窗口之外,还受拥塞窗口的影响,里面又包括了慢启动和拥塞算法的原理。TCP协议自面世以来经受了多年的实践应用而屹立不倒,里面蕴含的设计思想值得深入研究。
by Ryan.Ou