TCP快速重傳為什麼是三次冗餘ack,這個三次是怎麼定下來的?

我最近在學習TCP/IP協議,對於這個快速重傳的發明不是很清楚,第一次提問,求拍磚。


兩次duplicated ACK肯定是亂序造成的!
丟包肯定會造成三次duplicated ACK!

假定通信雙方如下,A發送4個TCP Segment 給B,編號如下,N-1成功到達,因為A收到B的ACK(N),其它按照到達順序,分別收到ACK(N)的數目:

A ---------&> B

A方發送順序N-1,N,N+1,N+2

B方到達順序

N-1,N,N+1,N+2
A收到1個ACK (N)

N-1,N,N+2,N+1
A收到1個ACK (N)

N-1,N+1,N,N+2
A收到2個ACK (N)

N-1,N+1,N+2,N
A收到3個ACK (N)

N-1,N+2,N,N+1
A收到2個ACK (N)

N-1,N+2,N+1,N
A收到3個ACK (N)


如果N丟了,沒有到達B

N-1,N+1,N+2
A收到3個ACK (N)

N-1,N+2,N+1
A收到3個ACK (N)

TCP segment 亂序 有2/5 = 40% 的概率會造成A收到三次 duplicated ACK(N);

而如果N丟了,則會100%概率A會收到三次duplicated ACK(N);

基於以上的統計,當A接收到三次 duplicated ACK(N)啟動 Fast Retransmit 演算法是合理的,即立馬retransmit N,可以起到Fast Recovery的功效,快速修復一個丟包對TCP管道的惡劣影響。

而如果A接收到二次 duplicated ACK(N),則一定說明是亂序造成的,即然是亂序,說明 數據都到達了B,B的TCP負責重新排序而已,沒有必要A再來啟動Fast Retransmit演算法。


補充閱讀
--------------------------------------------
TCP segment 亂序的由來

TCP segment 封裝在IP包里,如果IP包亂序,則相應TCP也會亂序,亂序的原因一般如下:

1)ECMP 負載均衡

多路徑的負載均衡,基於per-packet load balance,比如 packet 1,3,5…走路徑1,packet 2,4,6…走路徑2,很難保證packet 1 在 packet 2 之前到達目的地。

Per-session load balance 會基於TCP五元組來負載均衡,同一個TCP會話會走同一條路徑,克服多路徑造成的亂序。

2)路由器內部流量調度

有些路由器採用多個流量處理單元,比如packet 1,3,5…由處理單元1來處理,packet 2,4,6…由處理單元2來處理,也很難保證packet 1 在 packet 2 之前到達目的地。

TCP接收到亂序的segment,會放在自己的接收緩衝區,等所有亂序的segment 都順利到達,TCP重新排序,並將數據提交給 application。

亂序的segment 會佔用接收緩衝區,直接造成B advertised window size 變小,造成對方A發送window 一直在變小,影響A發送效率。

即使A不快速重傳,最後也會由retransmit timer timeout 超時重傳,但這個時候A的發送window 非常小,發送速率也從天上掉到了地下。

----------///--------
@鹿陽
分析的很好,在沒有fast retransmit / recovery 演算法之前,重傳依靠發送方的retransmit timeout,就是在timeout內如果沒有接收到對方的ACK,默認包丟了,發送方就重傳,包的丟失原因 1)包checksum 出錯 2)網路擁塞 3)網路斷,包括路由重收斂,但是發送方無法判斷是哪一種情況,於是採用最笨的辦法,就是將自己的發送速率減半,即CWND 減為1/2,這樣的方法對2是有效的,可以緩解網路擁塞,3則無所謂,反正網路斷了,無論發快發慢都會被丟;但對於1來說,丟包是因為偶爾的出錯引起,一丟包就對半減速不合理。於是有了fast retransmit 演算法,基於在反向還可以接收到ACK,可以認為網路並沒有斷,否則也接收不到ACK,如果在timeout 時間內沒有接收到&> 2 的duplicated ACK,則概率大事件為亂序,亂序無需重傳,接收方會進行排序工作;而如果接收到三個或三個以上的duplicated ACK,則大概率是丟包,可以邏輯推理,發送方可以接收ACK,則網路是通的,可能是1、2造成的,先不降速,重傳一次,如果接收到正確的ACK,則一切OK,流速依然(包出錯被丟)。而如果依然接收到duplicated ACK,則認為是網路擁塞造成的,此時降速則比較合理。


我也來說說個人看法:
為什麼確定該值為三,即使在RFC裡邊也沒有明確寫。
大致原因是因為網路傳輸是不可靠的,丟包、亂序和複製等情況,如果出現三次以上DupAck的就認為丟包的可能性很高,可以進入快速重傳機制。
希望明確以下幾點:
1、數據接收端,在收到失序數據包(可能是丟失、或亂序)時,需要馬上觸發DupACK。RFC 5681原話為:
"A TCP receiver SHOULD send an immediate duplicate ACK when an out-of-order segment arrives."
個人認為這是快速重傳等機制的最重要的基礎,否則快速重傳機制就失效了。
2、發送端收到三個DupAck,其實意思是總共四個相同的ACK,第一為正常確認ACK,後續三個為重複ACK。

另外:在實際抓包中,多數時候啟動快速重傳都會是在遠大於3個DupAck以後發生。


假設發送了分組n,n+1,n+2,並且分組n被接收並被確認.如果分組n+1和n+2在端到端的路徑上被重新排序)也就是說,被以n+2,n+1的順序接收),那麼在收到第一個冗餘ACK就重傳的策略下,在接收到分組n+2時將產生一個分組n的冗餘ACK,這將引起重傳發生.在接收到3個冗餘ACK才執行重傳的策略下,只有在分組n後面的兩個分組被正確接收,然而分組n+1沒有被接收的情況下,重傳才會發生.設計三個冗餘ACK策略的設計者可能感覺等待兩個分組(而不是一個)是在當需要時觸發快速重傳和當分組重新排序時不進行過早的重傳之間權衡的結果.


上面一個答案是自頂向下那本書中英文的答案,我簡單點說吧,其實這個設計是一種權衡。發送端收到了3個關於包n的冗餘ACK,說明n沒收到,但3個在n之後的包收到了,作者認為這種情況下快速重傳是一種最佳的權衡(其實我也不清楚具體原因)。如果快速重傳機制設置為收到2個冗餘ack就重傳的話,有可能會發生這種情況:發送n,n+1,n+2但是由於網路原因n+1,n+2先到了,這時候會產生2個n的冗餘ack,然後發送端就會重新發送n。


Suppose packets n, n+1, and n+2 are sent, and that packet n is received and ACKed. If
packets n+1 and n+2 are reordered along the end-to-end-path (i.e., are received in the order
n+2, n+1) then the receipt of packet n+2 will generate a duplicate ACK for n and would
trigger a retransmission under a policy of waiting only for second duplicate ACK for
retransmission. By waiting for a triple duplicate ACK, it must be the case that two packets
after packet n are correctly received, while n+1 was not received. The designers of the
triple duplicate ACK scheme probably felt that waiting for two packets (rather than 1) was
the right tradeoff between triggering a quick retransmission when needed, but not
retransmitting prematurely in the face of packet reordering.


說起來你可能不信,這種東西叫經驗值。


請問各位高手,我想問個問題,當收到第一次重複ACK或者第二次重複ACK,tcp會有什麼反應?還是什麼都不做?比如在slow start階段一下發了8個包,然後第二個丟了,後面陸陸續續收到3個重複ACK。我想問第一個重複ACK或者第二個重複ack,發送端會怎麼反應


推薦閱讀:

OSI模型中,一個協議應該屬於哪一層是以什麼為標準劃分的?
網關和路由器的區別是什麼?
網路編程必須使用socket嗎?
E2E RTT的具體含義?
使用tracert命令時,在一個節點後所有的節點都沒有數據,這是為什麼?

TAG:計算機網路 | TCPIP | 網路協議 |