TCP的拥塞控制
拥塞控制的一般原理
· 拥塞现象:即在某段时间里,对网络中的资源(带宽、缓存、处理能力等)的需求超过了该资源所提供的可用部分,导致网络性能变差。拥塞的最坏结果就是系统崩溃。
· 拥塞是由诸多因素产生的:
· 拥塞控制:即防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不至于过载。
- 拥塞控制是一个全局性的过程,涉及所有的主机、路由器,以及与降低网络性能相关的所有因素。
· 拥塞控制和流量控制的区别:
相对而言,拥塞控制是一个全局性的过程,而流量控制是点对点的。
但其实,某些拥塞控制算法会向发送方发送控制报文,告诉发送方网络出现拥塞,必须放慢发送速度,这与流量控制类似。
· 拥塞控制的基本思想就是让网络吞吐量慢慢上升,而不至于超过阈值:
· 拥塞控制的一般原理:
首先我们要知道,拥塞控制的基本前提是网络至少能够承受当前的负荷,而不是系统已经崩溃。
拥塞控制是一个动态问题,我们知道拥塞的成因是需求>可用量,因此我们的解决思路就是让需求<=可用量。
因此,我们提出两种解决拥塞的思路:
- 增加网络资源可用量。
- 减少用户对资源的需求。
· 开环控制和闭环控制:
· TCP采用的是闭环控制,闭环控制的措施:
· 监测网络拥塞的主要指标如下,这些指标的上升都意味着网络发生拥塞:
TCP的拥塞控制方法
· TCP采用基于窗口的方法进行拥塞控制。
· 拥塞窗口(Congestion Windows,cwnd)是由发送方维持的一个状态变量,其大小取决于网络拥塞程度,是动态变化的。
· 发送方的发送窗口不仅考虑接收方的接收窗口,还要考虑拥塞窗口,因此:
· 控制拥塞窗口的大小的原则很简单:没拥塞的话窗口就大一点,否则小一点。
· TCP使用4种拥塞控制方法如下:
慢开始(Slow-Start):由小到大逐渐增大拥塞窗口数值。
可以发现,使用慢开始算法后,每经过一个传输轮次(Transmission Round),拥塞窗口cwnd就加倍。
每次都翻倍的话,cwnd的增长速度是非常快的,这可能导致拥塞,因此我们引入慢开始门限ssthresh:
注意区分对于每一个确认报文cwnd+=1和每一个轮次cwnd*=2的区别,实际上是一样的,只是表示不同。
拥塞避免算法:和慢开始类似,都是让拥塞窗口缓慢增大,只不过这里是每经过一个传输轮次,拥塞窗口cwnd+=1,这样就可以使拥塞窗口按线性规律缓慢增长。
该算法目的在于迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够的时间处理队列中积压的分组。
所以实际上这个算法就是控制发送窗口的大小。
算法原理:无论是在慢开始阶段还是拥塞避免阶段,只要发送方判断网络出现拥塞(即重传计时器超时)就执行:
- ssthresh = max(cwnd/2, 2)
- cwnd = 1
- 执行慢开始算法
举个例子如下:
当TCP连接初始化的时候,cwnd=1,假设rwnd足够大,那么发送窗口swnd只由cwnd决定;初始化ssthresh=16。
- 0-4传输轮次:慢开始阶段,每经过一轮cwnd翻倍。
- 4-12传输轮次:cwnd到达ssthresh,变为拥塞避免,每经过一轮cwnd+1。
- 当cwnd=24时,网络出现超时,发送方判断出现阻塞,于是ssthresh=ssthresh/2=12,cwnd=1,重新进入慢开始。
- 13-17传输轮次:慢开始阶段,每经过一轮cwnd翻倍。
- 当cwnd=12时达到ssthresh,变为拥塞避免,每经过一轮cwnd+1。
- 21传输轮次:出现一个新情况,发送方一连收到3个对同一个报文段的重复确认(记为3-ACK),发送方改为执行快重传和快恢复算法。
快重传(Fast Retransmit):发送方只要一连收到3个重复确认,就知道接收方确实没有收到报文(因为接收方一直在等待,所以发送同一个ACK),此时应立即执行重传,这样发送方就不会等待超时从而误认为是网络拥塞。
使用快重传可以使整个网络的吞吐量提升20%。注意,快重传不是取消重传计时器,而是在某些情况下可以更早地执行重传。
快恢复(Fast Recovery):当发送方一连接收到3个重复确认时,由于发送方现在认为网络很可能没有发生阻塞,因此现在不执行慢开始,而是执行快恢复:
- 慢开始门限ssthresh = cwnd / 2;
- 新拥塞窗口cwnd = ssthresh;
- 开始执行拥塞避免算法
回到上面图的例子:21轮次的时候,发送方收到了3个相同的ACK,此时发送方知道有报文丢失,便执行快重传和快恢复,ssthresh = cwnd / 2 = 8,cwnd = ssthresh = 8,开始执行阻塞避免算法,每经过一个传输轮次cwnd+=1。
加法增大,乘法减小(AIMD):
从的来说,TCP拥塞控制算法流程图如下,刚刚提到的三种情况都有列出:(重点!)
TCP的运输连接管理
· TCP连接有三个阶段:连接建立->数据传输->连接释放。
· TCP连接有12个状态。(不需要记忆,但可以帮助我们理解整个工作过程)
TCP的连接建立
· TCP连接建立过程需要解决的问题:
· TCP连接建立的过程称为握手(Handshake),具体来说,是客户端和服务器之间交换三个TCP报文段,因此称为三次握手(Three-Way Handshake)。
· 为什么采用三次握手而不是两次:为了防止已经失效的连接请求突然又传送到了,因而产生错误。
- 假如A发送的连接请求在网络节点中停留时间过长,以致于A已经放弃这个连接请求(即释放了)后,请求才到达B,此时B认为这是一个正常的请求,就会给A发送确认,此时即使A收到了B的确认也会直接丢弃,因为A早已放弃该请求,B没收到A的确认,也不会建立连接。如果只有两次握手,那B收到A的请求之后给A回复后就会调用资源准备发送和接收数据,但A其实早已放弃该请求,B只会白白等待浪费资源,故需要三次握手。
· 三次握手具体过程如下:
- 一开始,Client和Server都是CLOSED状态。
- Server开启后变为LISTEN状态,监听来自远方的TCP连接请求。
- Client主动发送连接请求,变为SYN-SENT状态,报文中首部的SYN=1,选择序号seq=x,表明传输数据时第一个数据字节的编号为x。
- Server收到Client的TCP请求报文后,若同意,则发送确认,其中SYN=1,ACK=1,自己选择序号seq=y,确认号ack=x+1。
- Client收到Server的确认后,改变自己的状态为ESTABLISHED,并再次向B给出确认,ACK=1,seq=x+1,确认号ack=y+1。
- Client的TCP通知上层应用,连接已建立,Server收到Client确认后更新状态为ESTABLISHED。
· 实际上,连接建立的时候还需要协商很多参数,如窗口大小、缓冲区等,这里只演示最简单的情况。
TCP的连接释放
· TCP连接释放过程比较复杂,数据传输结束之后,通信双方都可释放连接。
· TCP连接释放过程需要交换4个TCP报文,我们称之为四次挥手(Four-Way Handshake)。
· 具体四次挥手流程如下:
- 数据传输结束之后,双方都可以释放连接,但一般都是Client释放。
- Client向Server发送释放报文段,并停止再发送数据,主动关闭TCP连接,该报文FIN=1(优雅地停止),seq=u,Client进入FIN-WAIT-1状态,等待Server的中断请求。
- Server收到Client的释放报文后,通知高层应用进程,并给Client发送确认,ACK=1,seq=v,ack=u+1,Server进入CLOSE-WAIT状态,表示收到并确认中断请求;Client进入FIN-WAIT-2半关闭状态,等待Server连接中断请求。此时,A->B方向的连接就成功被释放了,TCP处于半关闭状态,Server仍能给Client发送数据。
- 若Server也已经没有要给Client发送的数据,其应用进程就通知Server释放TCP连接,并给Client发送中断确认请求,FIN=1,ACK=1,seq=w,ack=u+1,进入LAST-ACK状态,等待Client确认中断请求。
- Client收到中断确认请求之后,发送中断请求确认,ACK=1,seq=u+1,ack=w+1,自身进入TIME-WAIT状态,要等待2MSL以确保Server能正确接收到中断确认请求。
- Server收到中断确认后,进入CLOSED;Client等待2MSL后,进入CLOSED。
· MSL指的是最长报文段寿命(Maximum Segment Lifetime,MSL),指任何报文段在网络上存在的最长时间,规定时间为2分钟,实际应用可以是30s、1min等。2MSL就是两倍MSL,因此,TIME-WAIT状态也称为2MSL状态。
TCP的有限状态机
· 其实就是我们刚刚说的建立和释放连接的状态变化: