一、流量控制简介
一条TCP连接的每一侧主机都为其设置了接收缓存,当TCP成功连接后,它发送的数据会放入接受缓存中。相关联的进程会从缓存中读取数据。但是存在一个问题,当某应用程序读取数据速率太慢,而发送数据一方不停的发送数据,会导致缓存区溢出,为了解决这类情况出现了流浪控制。
注意:UDP并不提供流量控制,报文段由于缓存溢出后可能会在接收方丢失掉。
二、流量控制具体过程
TCP为它的应用程序提供了流量控制服务(flow - control service )以消除发送方使接收方缓存溢出的可能性。
TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制。
TCP连接的双方都有一个接收窗口,并用RcvBuffer表示缓存接收大小。rwnd表示缓存区中剩余大小(rwnd是动态变化的)。
我们定义两个变量:
- LastByteRead:主机上的应用进程从缓存区读出的数据流最后一个字节的编号。
- LastByteRcvd:从网络中到达并且已放入主机进程缓存区中的数据流的最后一个字节的编号。
两个必须成立的公式:
LastByteRead — LastByteRcvd <= RcvBuffer
rwnd = RcvBuffer — [ LastByteRcvd — LastByteRead ]
当有一个A主机向B主机发送数据时:
主机B把rwnd值放入发送给主机A的报文段中,告诉主机A还有多少缓存大小。为了实现这一点,主机B必须跟踪几个与连接有关的变量。
主机A轮流跟踪两个变量,LastByteSent 和 LastByteAcked ,LastByteSent — LastByteAcked = 主机A发送到连接中但未被确认的数据量,通过将其控制在rwnd值以内,就可以保证主机A发送的数据到达主机B后不会溢出。
LastByteSent — LastByteAcked <= rwnd
三、存在的一个小问题
主机A向主机B发送数据
假设主机B中rwnd=0,即缓存区已经满了,并且主机B没有任何数据要发送给主机A ,当主机B缓存区读取完后,TCP并不会向主机A发送带有rwnd新值的新报文段。这样主机A会一直阻塞而不会发送新数据。为了解决这个问题,TCP中要求:当主机B的接收窗口为0时,主机A继续发送只有一个字节数据的报文段。这些报文段会被接收方接收,最终缓存区开始情况,并且确定报文里包含一个非0的rwnd值。