TCP通过滑动窗口的概念来进行流量控制
滑动窗口,可以理解成接收端所能提供的缓冲区大小。TCP利用一个滑动的窗口来告诉发送端对它所发送的数据能提供多大的缓 冲区。由于窗口由16位bit所定义,所以接收端TCP 能最大提供65535个字节的缓冲。由此,可以利用窗口大小和第一个数据的序列号计算出最大可接收的数据序列号。
对于TCP会话的发送方,任何时候在其发送缓存内的数据都可以分为4类,
- “已经发送并得到对端ACK的”,
- “已经发送但还未收到对端ACK的”,
- “未发送但对端允许发送的”,
- “未发送且对端不允许发送”。
“已经发送但还未收到对端ACK的”和“未发送但对端允许发送的”这两部分数据称之为发送窗口(中间两部分)。
滑动窗口本质上是描述接受方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据。如果发送方收到接受方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接受方发送窗口大小不为0的数据报的到来。
A—————C—————B
如上图,A与B之间建立TCP连接,滑动窗口实现有两个作用:
由于对称性,只考虑A端发送窗口和B端接收窗口,有如下两个作用
1B端来不及处理接收数据(控制不同速率主机间的同步),这时,A通过B端通知的接收窗口而减缓数据的发送。
2B端来得及处理接收数据,但是在A与B之间某处如C,使得AB之间的整体带宽性能较差,此时,A端根据拥塞处理策略(慢启动,加倍递减和缓慢增加)来更新窗口,以决定数据的发送。
与固定大小的滑窗协议相比,TCP采用可变大小的滑窗协议是为了取得更好的性能。
TCP是一个广域网协议,而广域网环境下的路由器和主机,各自有着不同的性能和处理能力,在这种情况下,采用固定窗口大小的滑窗协议会引起性能上的损失。TCP规定窗口的大小是由接收方通告的,通过采取慢启动和拥塞避免算法等机制来使带宽和性能取得最佳。
滑动窗口实现面向流的可靠性
TCP是双工的协议,会话的双方都可以同时接收、发送数据。TCP会话的双方都各自维护一个“发送窗口”和一个“接收窗口”。
最基本的传输可靠性来源于“确认重传”机制。
TCP的滑动窗口的可靠性也是建立在“确认重传”基础上的。
发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。
对ACK的再认识,ack通常被理解为收到数据后给出的一个确认ACK,ACK包含两个非常重要的信息:
一是期望接收到的下一字节的序号n,该n代表接收方已经接收到了前n-1字节数据,此时如果接收方收到第n+1字节数据而不是第n字节数据,接收方是不会发送序号为n+2的ACK的。举个例子,假如接收端收到1-1024字节,它会发送一个确认号为1025的ACK,但是接下来收到的是 2049-3072,它是不会发送确认号为3072的ACK,而依旧发送1025的ACK。
二是当前的窗口大小m,如此发送方在接收到ACK包含的这两个数据后就可以计算出还可以发送多少字节的数据给对方,假定当前发送方已发送到第x字节,则可以发送的字节数就是y=m-(x-n).这就是滑动窗口控制流量的基本原理.
我们知 道窗口大小是与确认序号相对应的。发送方计算它的可用窗口,该窗口表明多少数据可以立即被发送。当接收方确认数据后,这个滑动窗口不时地向右移动。窗口两 个边沿的相对运动增加或减少了窗口的大小。我们使用三个术语来描述窗口左右边沿的运动:
- 称窗口左边沿向右边沿靠近为窗口合拢。这种现象发生在数据被发送和确认时。
- 当窗口右边沿向右移动时将允许发送更多的数据,我们称之为窗口张开。这种现象发生在另一端的接收进程读取已经确认的数据并释放了T C P的接收缓存时。
- 当右边缘向左移动时,称之为窗口收缩。
——TCP的滑动窗口机制:基本的数据单位不是数据段,而是字节;每个窗口用三个指针表示,第一个指向窗口的第一个字节,第二个指向窗口中马上要发送的字节,第三个指向窗口的最后一个字节。
1) 累积确认:接收方对某个编号进行确认,该编号之前的数据必须都已接收到了,从而有时候前面窗口的数据没有接受到,就必须暂存数据,并在接收到前面的其他数据后进行累积确认
a) 优点:允许发送方在对数据进行重发时发送更多的数据,无需对丢失的确认进行重发;为确认数据段也会丢失,但只要下一个确认能够到达对方就无需对前一个确认进行重发
b) 缺点:若第一个窗口的数据丢失,则收到的确认好一直都是关于之前数据的确认,得不到关于新发送的数据包的确认;从而无法确定从该窗口开始的数据包哪些成功发送,哪些丢失了
2)发送方窗口不能大于接收方窗口,凡是ACK 置为1 的数据段都应该将自己接收窗口的当前大小填入TCP数据段头部的窗口字段中,通知给发送方