TCP的流量控制就是TCP接收端对发送端发送多少字节的数据进行控制,防止接收端处理不及而丢失数据。差错控制就是保证接收端接收的数据是完整未受损伤的,是可靠性的重要保证。
这里以TCP连接的建立过程说明流量控制,则流量控制的过程如下:
- TCP发送端向接收端发送一个SYN=1、seqNo=100的连接请求。这里的SYN=1表示一个建立连接的标志位,seqNo表示发送端发送数据的起始字节的编号是100
- 接收端收到SYN=1、seqNo=100的报文后,给客户端发送ACK=1、seqNo=1000、ackNo=101、rwnd=800的响应报文,告诉发送端,我如果向你发送数据则我这边的数据的字节起始编号是1000,而且你刚才发送的连接请求我已经收到了,我下一个希望接收编号是101的字节,还告诉发送端发送窗口是800,并且接收端的接收窗口也是800字节
- 发送端收到后,发送端的连接就建立了,于是给接收端发送ackNo=1001、ACK=1的报文,接收端收到后知道发送端已经收到刚才自己发的报文,所以接收端的连接也建立了。
- 当两边的连接建立后就可以发送数据了,首先发送端发送seqNo=101,Data=200bytes的数据。
- 接收端收到这200字节的数据后,接收窗口由800变为600(因为窗口缓存是800字节),并向发送端发送ACK=1、seqNo=301、rwnd=600的报文,告诉发送端你发送的200字节我已经收到了,下次发送的字节的起始编号是301,你的发送窗口要变为600了
- 发送端收到后,知道刚才发送的200字节一杯确认了,于是把发送窗口向右移动200字节,这样发送窗口就变为600字节了。之后,发送继续向接收端发送数据,发送seqNo=301,Data=300bytes的报文,向接收端发送起始编号为301且长度是300的数据
- 接收端收到后,把窗口减小为300字节,这时接收进程从接受缓存中拉取了100字节的数据,于是接收窗口的大小重新变为400字节,于是向发送端发送ACK=1、ackNo=601、rwnd=400的报文,告诉发送端你刚才发送的300字节数据我已经收到了,我下次希望接收的字节起始编号是601,你要把发送窗口继续减小为400字节
- 发送端收到后,知道刚才发送的300字节被确认了,于是把发送窗口向右移动,并不得不继续较小发送窗口为400字节
- 一会后,接收进程从接收缓存中拉取了200字节的数据,接收窗口变为600字节,于是接收端向发送端发送ACK=1、ackNo=601、rwnd=600的报文,告诉发送端窗口可以增大为600字节了
- 后面的过程与此类似,以此类推
从这个过程中,可以发现,发送窗口的大小是受到接收窗口的控制的。发送窗口必须根据接收端的大小及时调整发送窗口的大小,这个机制保证了每次TCP传输的数据量都是接收端可以及时处理的。不过这个过程中可能存在一个特例,就是当发送端每次只发送一个字节的数据的时候后者接收端处理数据的速度每一次只有一个1字节或者两者都有的时候,每次发送的报文段都很短,就会导致低效率,以发送端每次发送1字节为例,数据1字节、TCP首部20字节、IP首部20字节,这样为了发送1字节需要使用41字节发送浪费率达到40/41,加上数据链路层以及物理层的开销,可能这个数值还更大。这个问题有一个术语叫糊涂窗口综合征。有兴趣可以自己了解一下