流量控制针对的是发送方和接收方速度不匹配的问题(比如经典的fast sender and slow receiver问题,接收方缓存大小与发送速率不匹配),所提供一种速度匹配服务,遏制发送速率使接收方应用程序的读取速率与之相适应。
主要的方法有:
- Stop-and-wait 这个也是最简单粗暴的,发一个分组就等对方一个ACK回应然后再发,收不到ACK就不发了
- 滑动窗口, 接收方在一个窗口都满了以后才会发送ACK确认并要求发送下一个窗口。
滑动窗口协议
滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度。
在TCP发送缓存内的数据都可以分为4类:
- 已经发送并得到对端ACK
- 已经发送但还未收到对端ACK
- 未发送但对端允许发送
- 未发送且对端不允许发送
已经发送但还未收到对端ACK和未发送但对端允许发送这2部分数据称之为发送窗口。
滑动窗口.jpg
原理
ACK报文包含2个重要信息:
- 期望接收到的下一个字节的序号 n,该 n 表示接收方已经接收到了前 n-1 个字节数据。
- 当前窗口大小m。
如此发送方在接收到的ACK包含的这2个数据后就可以计算出还可以发送多少字节的数据给对方,假定当前发送方已发送到第x个字节,则可以发送的字节数就是y=m-(x-n)。
例子
例图.jpg- 窗口左边沿向右边沿靠近为窗口合拢。这种现象发生在数据被发送和确认
- 当窗口右边沿向右移动时为窗口张开。这种现象发生在另一端的接收进程读取已经确认的数据并释放TCP接收缓存空间,此时将允许发送更多的数据,
- 当右边沿向左移动时,我们称之为窗口收缩。RFC强烈建议不适用这种方式。
从这个例子里我们可以总结一下几点:
- 发送方不必发送一个全窗口大小的数据
- 来自接收方的一个报文段确认数据并把窗口向右边滑动。
- 窗口的大小可以减小,但是窗口右边沿却不能够向左移动。
- 接收方在发送一个ACK前不必等待窗口填满。
窗口大小
由接收方提供的窗口大小通常可以由接收进程控制,Socket API允许进程设置发送和接收缓存大大小。接收缓存的大小是该连接上所能够通告的最大窗口大下。
参考资料
《TCP/IP详解 卷1:协议》[美] W.Richard Stevens
网友评论