流量控制
在TCP传输中,操作系统会把数据分拆成一个一个TCP包,发送端会将需要发送的TCP包放到发送缓冲区,而接收端则将需要接收的数据放到接收缓冲区。根据当前接收端的处理能力,调整发送端的滑动窗口大小,来控制数据传输的速率。
滑动窗口
滑动窗口分为发送端和接收端,分别对应发送窗口和接收窗口。
发送窗口
包含四种状态数据:已发送且确认、已发送未确认、未发送且待发送、未发送且不可发送。
上图标识出四种状态数据,发送窗口就是蓝色框中的范围,大小是11,其中数据5是下一个确认的数据,数据10是下一个需要发送的数据。
接收窗口
其中数据5表示下一个接收的数据,而接收窗口的大小是5。
流量控制的流程:
假设双方握手后,初始化滑动窗口是50,这时候发送端会发送大小50的数据,而由于接收端处理能力的问题,只能处理20的数据,剩下30的数据放在接收缓冲区,这时候接收端就会返回window size为20给发送端,让它的滑动窗口缩小到20,下次传输的数据大小就是20,在传输过程中,通过不断的控制滑动窗口的大小来进行流量控制。
Q:如果滑动窗口大小为零,将会发生什么事?
A:会设置探测定时器,如果超时前收到接收方的反馈,window size > 0,则恢复正常。如果超时了,则发送一个数据,并且重新计时,并记录超时次数。如果超出超时限制,会强制关闭TCP连接。
拥塞控制
在上面介绍了滑动窗口,它反映了接收端的处理能力,但不能反映出当前网络拥堵环境。所以接下来介绍的是发送端的拥塞窗口。
拥塞窗口
拥塞窗口其实就是对于发送窗口的限制, 来控制目前自己能传输数据量的大小。
所以发送窗口收到两个窗口状态的限制,拥塞窗口cwnd和接收窗口rwnd
那么发送窗口大小公式是: min(cwnd, rwnd)
流量控制是控制滑动窗口大小,那么拥塞控制就是控制拥塞窗口的大小。
基本算法
控制拥塞窗口涉及的算法大概有三个
- 慢开始
- 拥塞避免
- 快重传和快恢复
慢开始
慢开始其实就是跟字面意思一样,逐渐地增大拥塞窗口去探测当前的网络情况。
- TCP握手连接
- 初始化拥塞窗口,假设为1
- 双方开始传输数据,每次收到一次确认回复ACK,则拥塞窗口大小+1,所以每过一次数据轮换RTT,拥塞窗口大小*2。第一轮:2,第二轮:4,第三轮:8,以此类推,成2的指数级增长。
但增长到慢开始阈值的时候,增长的速度就会慢下来,这时候就进入拥塞避免算法。
拥塞避免
当拥塞窗口达到慢开始阈值的时候,由速率由原来的+1/ACK变成+(1/cwnd)/ACK,也就是每过一轮RTT之后,拥塞窗口的大小才+1,而不是翻倍了。
快重传和快恢复
快重传
在TCP传输的过程中,可能因为网络原因造成丢包,接收方就会返回丢失包的前一个序号,就算收到后序包,也会重复返回该序号。
比如:需要传输1-2-3-4-5数据,3号包丢了,其他全部到达,则接收方会返回1-2-2-2-2的序号回去,当发送端接收到3个重复的ACK序号的时候,就能知道哪个数据丢包了,马上进行重传,而不需要等待超时重传时间。
Q:如果ACK在网络中也丢包呢?
A:如果一直没有收到ACK,则达到超时时间后,对丢失的3号包进行重传。如果全部已经到达,但只有3,4包的ACK丢失了,只收到5号包的ACK的话,那么发送端就认为接收方已经接受所有数据。因为收到5号包的ACK就表示,全部数据已经收到,否则只有回复丢失包的前一个序号2。
Q:如果只丢失了3号包,4,5号包需要重传吗?
A:不需要,这就是选择性重传的机制,接收端会在报文头部中加上SACK的属性,告诉发送端那些数据区间已经收到了,只需要让它再次传输丢失的包即可。
快恢复
在快重传的介绍中,当收到3个重复的ACK的时候,就会意识到丢包,感觉网络环境不好,这时候就会进入快恢复的阶段
- 慢开始阈值减半。
- cwnd的值变成阈值+3。注:+3是因为收到3个重复的ACK,表明已经有3个数据包丢失在网络了
- cwnd继续进行拥塞避免的状态,每次线性增加。