1. 程式人生 > >TCP-IP詳解:超時重傳機制

TCP-IP詳解:超時重傳機制

參考教材:TCP-IP Guide 

超時重傳是TCP保證資料傳輸可靠性的又一大措施,本文主要介紹重傳TCP報文的兩大舉措:超時重傳和快速重傳

超時重傳機制

超時重傳指的是,傳送資料包在一定的時間週期內沒有收到相應的ACK,等待一定的時間,超時之後就認為這個資料包丟失,就會重新發送。這個等待時間被稱為RTO.  

檢測丟失segment的方法從概念上講還是比較簡單的,每一次開始傳送一個TCP segment的時候,就啟動重傳定時器,定時器的時間一開始是一個預設的值(Linux 規定為1s),隨著通訊的變化以及時間的推移,這個定時器的溢位值是不斷的在變化的,有相關演算法計算RTO[參考:文章....],如果在ACK收到之前,定時器到期,協議棧就會認為這個片段被丟失,重新傳送資料。

TCP在實現重傳機制的時候,需要保證能夠在同一時刻有效的處理多個沒有被確認的ACK,也保證在合適的時候對每一個片段進行重傳,有這樣幾點原則:

1 . 這些被髮送的片段放在一個視窗中,等待被確認,沒有確認不會從視窗中移走,定時器在重傳時間到期內,每個片段的位置不變,這個地方其實在滑動視窗的時候也有提到過

2 .只有等到ACK收到的時候,變成傳送並ACK的片段,才會被從視窗中移走。

3 .如果定時器到期沒有收到對應ACK, 就重傳這個TCP segment

重傳之後也沒有辦法完全保證,資料段一定被收到,所以仍然會重置定時器,等待ACK,如果定時器到期還是沒有收到ACK,繼續重傳,這個過程重傳的TCP segment一直留著佇列之內。

舉個重傳的例子:

1. Server 傳送80個位元組 Part1,seq = 1 

2. Server 傳送120個位元組Part2,Seq = 81

3. Server傳送160個位元組Part3,Seq = 201,此包由於其他原因丟失

4. Client收到前2個報文段,併發送ACK = 201

5. Server傳送140個位元組Part4, Seq = 361

7. Server收到Client對於前兩個報文段的ACK,將2個報文從視窗中移除,視窗有200個位元組的餘量

8. 報文3的重傳定時器到期,沒有收到ACK,進行重傳

9. 這個時候Client已經收到報文4,存放在緩衝區中,也不會發送ACK【累計通知,傳送ACK就表示3也收到了】

,等待報文3,報文3收到之後,一塊對3,4進行確認

10. Server收到確認之後,將報文3,4移除視窗,所有資料傳送完成


這種方式會面臨一個問題:客戶端在等待報文3的時候,伺服器如何處理報文4, 客戶端這個期間內並沒有傳送任何報文,伺服器並不知道報文3和報文4的狀態,報文4可能會丟失,也可能會被客戶端接收,那麼如果超時了,我到底值該傳送報文3 ,還是報文3和報文4 呢?

總結起來就是2中處理

1. 定時器溢位,重傳3

2. 定時器溢位,重傳3,4

對於重傳時間是如何計算的問題,在RFC2988中也提供了一種至今Linux使用的方案,詳細介紹可以參考文章:TCP-IP詳解 RTT and RTO

對於定時器溢位的問題,就來介紹一下 快速重傳機制。

快速重傳機制

在超時重傳中,重點是定時器溢位超時了才認為傳送的資料包丟失,快速重傳機制,實現了另外的一種丟包評定標準,即如果我連續收到3次dup ACK,傳送方就認為這個seq的包丟失了,立刻進行重傳,這樣如果接收端回覆及時的話,基本就是在重傳定時器到期之前,提高了重傳的效率。

在傳輸過程中會出現out-of-order的現象,但是在滑動視窗中會有嚴格的順序控制,假設有4,5,6三個待接收的資料包,先收到了5,6,協議棧是不會回覆對5,6包的確認,而是根據TCP協議的規定,當接收方收到亂序片段時,需要重複傳送ACK, 在這個地方會發送報文4 seq的ACK,表明需要報文4沒有被接收到,如果此後收到的是報文7,那麼仍然要回報文4 seq的ACK,如果連續傳送3個 dup ACK,接收端認為這個片段已經丟失,進行快速重傳。

看一個簡單的例子:這是下載過程中網路不好抓的tcpdump

1. 145/153/170 是3個dup ACK

2.  171包,快速重傳


不過快速重傳能夠解決超時的問題,但是對於之前討論的究竟重傳哪些包的問題,依然不能有效的解決,這就需要TCP中提供的SACK機制來解決。

參考文章