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擁塞控制的實現,具體接受後續再補上了。