tcp 實現可靠傳輸的方式之一,是通過序列號與確認應答。
在 tcp 中,當傳送端的資料到達接收主機時,接收端主機會返回乙個確認應答訊息,表示已收到訊息。
但在錯綜複雜的網路,並不一定能如上圖那麼順利能正常的資料傳輸,萬一資料在傳輸過程中丟失了呢?
所以 tcp 針對資料報丟失的情況,會用重傳機制解決。
接下來說說常見的重傳機制:
重傳機制的其中乙個方式,就是在傳送資料時,設定乙個定時器,當超過指定的時間後,沒有收到對方的ack
確認應答報文,就會重發該資料,也就是我們常說的超時重傳。
tcp 會在以下兩種情況發生超時重傳:
超時時間應該設定為多少呢?我們先來了解一下什麼是
rtt
(round-trip time 往返時延),從下圖我們就可以知道:
rtt
就是資料從網路一端傳送到另一端所需的時間,也就是包的往返時間。
超時重傳時間是以rto
(retransmission timeout 超時重傳時間)表示。
假設在重傳的情況下,超時時間rto
「較長或較短」時,會發生什麼事情呢?
上圖中有兩種超時時間不同的情況:
精確的測量超時時間rto
的值是非常重要的,這可讓我們的重傳機制更高效。
根據上述的兩種情況,我們可以得知,超時重傳時間 rto 的值應該略大於報文往返 rtt 的值。
至此,可能大家覺得超時重傳時間rto
的值計算,也不是很複雜嘛。
好像就是在傳送端發包時記下t0
,然後接收端再把這個ack
回來時再記乙個t1
,於是rtt = t1 – t0
。沒那麼簡單,這只是乙個取樣,不能代表普遍情況。
實際上「報文往返 rtt 的值」是經常變化的,因為我們的網路也是時常變化的。也就因為「報文往返 rtt 的值」 是經常波動變化的,所以「超時重傳時間 rto 的值」應該是乙個動態變化的值。
我們來看看 linux 是如何計算rto
的呢?
估計往返時間,通常需要取樣以下兩個:
rfc6289 建議使用以下的公式計算 rto:
其中srtt
是計算平滑的rtt ,devrtr
是計算平滑的rtt 與 最新 rtt 的差距。
在 linux 下,α = 0.125,β = 0.25, μ = 1,∂ = 4。別問怎麼來的,問就是大量實驗中調出來的。
如果超時重發的資料,再次超時的時候,又需要重傳的時候,tcp 的策略是超時間隔加倍。
也就是每當遇到一次超時重傳的時候,都會將下一次超時時間間隔設為先前值的兩倍。兩次超時,就說明網路環境差,不宜頻繁反**送。
超時觸發重傳存在的問題是,超時週期可能相對較長。那是不是可以有更快的方式呢?
於是就可以用「快速重傳」機制來解決超時重發的時間等待。
tcp 還有另外一種快速重傳(fast retransmit)機制,它不以時間為驅動,而是以資料驅動重傳。
快速重傳機制,是如何工作的呢?其實很簡單,一圖勝千言。
在上圖,傳送方發出了 1,2,3,4,5 份資料:
所以,快速重傳的工作方式是當收到三個相同的 ack 報文時,會在定時器過期之前,重傳丟失的報文段。
快速重傳機制只解決了乙個問題,就是超時時間的問題,但是它依然面臨著另外乙個問題。就是重傳的時候,是重傳之前的乙個,還是重傳所有的問題。
比如對於上面的例子,是重傳 seq2 呢?還是重傳 seq2、seq3、seq4、seq5 呢?因為傳送端並不清楚這連續的三個 ack 2 是誰傳回來的。
根據 tcp 不同的實現,以上兩種情況都是有可能的。可見,這是一把雙刃劍。
為了解決不知道該重傳哪些 tcp 報文,於是就有sack
方法。
還有一種實現重傳機制的方式叫:sack
( selective acknowledgment 選擇性確認)。
這種方式需要在 tcp 頭部「選項」字段裡加乙個sack
的東西,它可以將快取的地圖傳送給傳送方,這樣傳送方就可以知道哪些資料收到了,哪些資料沒收到,知道了這些資訊,就可以只重傳丟失的資料。
如下圖,傳送方收到了三次同樣的 ack 確認報文,於是就會觸發快速重發機制,通過sack
資訊發現只有200~299
這段資料丟失,則重發時,就只選擇了這個 tcp 段進行重複。
如果要支援sack
,必須雙方都要支援。在 linux 下,可以通過net.ipv4.tcp_sack
引數開啟這個功能(linux 2.4 後預設開啟)。
duplicate sack 又稱d-sack
,其主要使用了 sack 來告訴「傳送方」有哪些資料被重複接收了。
下面舉例兩個栗子,來說明d-sack
的作用。
栗子一號:ack 丟包
栗子二號:網路延時
可見,d-sack
有這麼幾個好處:
可以讓「傳送方」知道,是發出去的包丟了,還是接收方回應的 ack 包丟了;
可以知道是不是「傳送方」的資料報被網路延遲了;
可以知道網路中是不是把「傳送方」的資料報給複製了;
在 linux 下可以通過net.ipv4.tcp_dsack
引數開啟/關閉這個功能(linux 2.4 後預設開啟)。
TCP IP 重傳演算法
重傳定時器 tcp 必須維護乙個重傳定時器,以進行超時重傳 問題 如何設定超時時間間隔 rto?時間間隔太短則可能導致大量不必要的重傳 太長則導致效能下降 tcp 採用了乙個高度動態的演算法,來不斷的調整時間間隔,這個演算法就是 jacobson 1988 演算法 在此演算法中,tcp 需要維護幾個...
TCP重傳機制
tcp進行傳輸時,發出去的請求包在規定時間內沒有收到ack,不管是請求包丟失,還是ack包丟失,還是網路延遲,總之,這裡都是需要有個重傳機制的。常見的導致重傳情況有 資料報傳輸途中丟失 接收端的ack確認報文在傳輸途中丟失 接收端異常未響應ack或被接收端丟棄。tcp的重傳機制有兩種 超時重傳和快速...
TCP IP學習筆記 超時重傳
當網路中出現擁塞,client端在給定的時間收不到server端傳送的ack資訊,那麼client就會認為是包丟失了。此時client就需要重新傳輸包,從包丟失到包重傳這個時間間隔就是rto。為了解決上面的問題,提出了慢啟動演算法和擁塞避免演算法,具體過程如下 當我們傳送的資料報出現亂序時,這個時候...