1986年,从LBL到UC Berkeley的网络吞吐由于拥塞出现了从32Kbps到40bps的急剧降低,Van Jacobson 在1988年的论文《Congestion Avoidance and Control》从这个问题出发,提出了数据包守恒定律以及慢启动、拥塞控制和快重传的算法,在1990年又提出了快恢复算法。算法
在一个运行平稳的TCP链接中流动的数据包应该是守恒的,意思是当只有旧的数据包被成功传输到对端后,新的数据包才能加入到链接中。在TCP协议中,咱们可使用ack来做为判断数据包是否已经成功到达对端的依据,就是说当发送端收到good ack(大于发送端当前已经收到的最大ack的ack)时,它就能够发送新的数据包了。这种根据ack来决定继续发送数据包的机制就叫作self clocking(也叫作ack clocking)。网络
经过数据包守恒原则,咱们知道能够经过ack来决定是否发送新的数据,而要收到ack就要先发送数据。慢启动就开始发送数据时的行为控制。慢启动的整体思路就是从一个很低的初始值开始,逐渐增长数据发送的速度,直到达到超时或者丢包为止。慢启动的实现思路以下:code
能够预见,在没有出现超时或者丢包时,慢启动增加的速度是指数级的,因此慢启动实际上并无那么“慢”,“慢”是慢在它的起点只有1个MSS。ci
前面提到,慢启动的目的是逐渐增长发送速度进行试探,直到出现网络拥塞,而真正出现拥塞时又该怎么作呢,就是“拥塞避免”所作的事情了。拥塞避免主要由两部分组成:资源
而拥塞避免的实现思路以下:io
这里的两个变动cwnd的行为一般称为“乘法减少”和“加法增大”。class
值得注意的是,慢启动和拥塞避免其实是两个不一样的算法,它们一个用于试探网络资源的上限,另外一个用于资源使用率达到或者接近上限时的行为。在1988年的论文中给出了一个结合了慢启动和拥塞避免的算法,具体实现思路以下:变量
cwnd<ssthresh
,cwnd+=1
(慢启动阶段,窗口指数级别增长)cwnd+=1/cwdn
(拥塞避免阶段,窗口线性增长)快速重传的目的就是让发送端尽快感知到丢包。TCP发送方在每发送一个分段时会启动一个计时器,若是相应的数据包确认没在特定时间内被送回,发送方就假设这个分段在网络上丢失了,须要重发。这也是TCP用来估计RTT的测量方法。sed
重复确认基于如下过程:若是接收方接收到一个数据分段,就会将该分段的序列号加上数据字节长的值,做为分段确认的确认号,发送回发送方,表示指望发送方发送下一个序列号的分段。可是若是接收方提早收到更大的序列号的分段,或者说接收到无序到达的分段,接收方须要当即使用以前的确认号发送分段确认。此时若是发送方收到接收方相同确认号的分段确认超过1次,而且该对应序列号的分段超时计时器仍没超时的话,则这就是出现重复确认,须要进入快速重传。方法
快送重传就是基于如下机制:若是假设重复阈值为3,当发送方收到4次相同确认号的分段确认(第1次收到确认指望序列号,加3次重复的指望序列号确认)时,则能够认为继续发送更高序列号的分段将会被接受方丢弃,并且会没法有序送达。发送方应该忽略超时计时器的等待重发,当即重发重复分段确认中确认号对应序列号的分段。
这里先列举各个TCP拥塞控制的实现,具体接受后续再补上了。