TCP除了有重傳定時器來保證將丟失的數據重傳以外,還有一些輔助算法用來協助完成數據的重傳。
我們認識到在收到一個失序的報文段時, T C P立即需要產生一個 A C K(一個重復的 A C K)。這個重復的 A C K不應該被遲延(tcp需要ack,可是為了效率以及考慮到資源消耗等問題,並不是每發送一個數據都要等待ack,而是盡可能利用窗口機制,積累發送ack的,此處知悉便可)。該重復的 A C K的目的在於讓對方知道收到一個失序的報文段,並告訴對方自己希望收到的序號。
由於我們不知道一個重復的 A C K是由一個丟失的報文段引起的,還是由於僅僅出現了幾個報文段的重新排序,因此我們等待少量重復的 A C K到來。假如這只是一些報文段的重新排序,則在重新排序的報文段被處理並產生一個新的 A C K之前,只可能產生 1 ~ 2個重復的 A C K。如果一連串收到 3個或3個以上的重復 A C K,就非常可能是一個報文段丟失了。於是我們就重傳丟失的數據報文段,而無需等待超時定時器溢出。這就是快速重傳算法。
簡單解釋一下為什么接收端接收到3個重復ack就會認定報文丟失而啟動快速重傳:
一個報文談不上順序,最少兩個報文才有順序的概念,正如字節序一樣,utf8以一個字節為編碼單位,因此就沒有字節序的問題,同樣的,僅僅來了一個報文也不能說它對於當前按序的報文來講是亂序的,只有當第二個報文到來的時候,如果當前按序報文,第一個報文,第二個報文拼不成順序才能說明后來的這兩個報文是亂序的,當然這也是一種權衡的結果,正如三次握手為何是三次一樣,即使接收端收到了第三個亂序報文,仍有可能被第四個填充后成為按序報文,沒完沒了等下去是不行的,必須在發送端接收到確定的,不是很大的數目冗余ack的時候進入快速重傳,同時也不能頻繁的快速重傳,因此就選擇了3個冗余ack,當然這個數字是可以配置的。說白了,可以理解為這是考慮各方面性能及消耗而人為設定的一個閾值。
接下來執行的不是慢啟動算法而是擁塞避免算法。這就是快速恢復算法(在這種情況下沒有執行慢啟動的原因是由於收到重復的 A C K不僅僅告訴我們一個分組丟失了。由於接收方只有在收到另一個報文段時才會產生重復的 A C K,而該報文段已經離開了網絡並進入了接收方的緩存。也就是說,在收發兩端之間仍然有流動的數據,而我們不想執行慢啟動來突然減少數據流)。
快速恢復算法實現:
1) 當收到第3個重復的A C K時,將s s t h re s h設置為當前擁塞窗口 c w n d的一半。重傳丟失的報文段。設置c w n d為s s t h re s h加上3倍的報文段大小。
2) 每次收到另一個重復的 A C K時, c w n d增加1個報文段大小並發送 1個分組(如果新的c w n d允許發送) 。
3) 當下一個確認新數據的 A C K到達時,設置c w n d為s s t h re s h(在第1步中設置的值)。這個A C K應該是在進行重傳后的一個往返時間內對步驟 1中重傳的確認。另外,這個 A C K也應該是對丟失的分組和收到的第 1個重復的A C K之間的所有中間報文段的確認。這一步采用的是擁塞避免,因為當分組丟失時我們將當前的速率減半。
T C P將忽略I C M P主機不可達的差錯並堅持重傳 ,而且采用指數退避方法進行重傳,減少網絡沖突(和保證共享資源的公平性??)。