前言
有时候我们去学习TCP的相关知识,可以先从字面意思着手,字面意思也许就是这个知识点最本质的说明,因为对TCP来说,它不会无缘无故的起个和自己完全不搭的名字,比如说TCP的快速重传和快速恢复。
TCP的快速重传与快速恢复
如果TCP的发送方连续收到3个或3个以上的对同一报文确认的重复ACK,那么TCP发送方就会重传该报文。
快速重传到底"快"在哪里?
我们通常说快慢,都有一个比较的对象,那就是谁比谁快,谁比谁慢。 通常情况下,发送端发送数据,会相应的启动超时重传定时器,如果在超时重传定时器溢出时还未收到对端发过来的ACK,那么发送端会重传报文,这个是TCP的超时重传机制。快速重传中的快就是不用等待超时重传定时器溢出,直接重传报文, 所以TCP快速重传中的"快"是相对于超时重传而言的。
快速重传的依据是发送方收到3次重复的ACK,为什么不是1次或者2次?
发送方收到重复ACK一般分为两种情况:
丢包:某个序列号靠前的报文丢失
乱序:各个报文在网络中独立路由,序列号靠前的报文较序列号靠后的报文后到达接收端,这就是乱序
对于接收方来说,只要序列号靠前的报文没有到达,无论后面收到多少的报文,接收方都会发送ACK,ACK的确认序列号是那个序列号靠前的报文的序列号N+1.
对于发送方来说,它是根据这两种情况下收到的重复ACK来区分的。所以两次duplicated ACK肯定是乱序造成的!
丢包肯定会造成三次duplicated ACK! 如果是报文丢失了,那么会一直收到重复ACK,所以我们用3次重复的ACK作为区分依据。
快速重传的目的是什么
快速重传的目的是保证在网络状态良好的情况下,避免TCP的发送方降低发送速度,从而降低网络的利用率。因为对于发送发来说一旦收不到ACK就会认为网络拥塞,进而开始慢启动,减小cwnd为1.如果对于网络拥塞的情况下无可厚非,但是试想如果是网络状态良好的情况下,发生了丢包,发送方如果立马就减小cwnd,就会降低网络的利用率。
所以快速重传可以使TCP的发送方立马知道报文丢失了,立马重传报文而且不用降低发送速度。测试表明,快速重传可以使网络吞吐量提高20%左右。
快速重传过程中cwnd 与 ssthresh的变化
快速重传做的事情有:
把ssthresh设置为cwnd的一半
把cwnd再设置为ssthresh的值(具体实现有些为ssthresh+3)
重新进入拥塞避免阶段。
正是因为快速重传以后直接进入拥塞避免阶段,而不是慢启动,所以叫快速恢复。
《TCPIP协议详解.卷1》中描述的该算法:
当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的报文段。设置cwnd为ssthresh加上3倍的报文段大小。
每次收到另一个重复的 ACK 时,cwnd增加1个报文段大小并发送 1 个分组(如果新的cwnd允许发送)。
当下一个确认新数据的ACK到达时,设置cwnd为ssthresh(在第1步中设置的值)。这个ACK应该是在进行重传后的一个往返时间内对步骤 1 中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第1个重复的ACK之间的所有中间报文段的确认。