1. 程式人生 > >超時重傳+擁塞控制

超時重傳+擁塞控制

超時重傳+擁塞控制

https://www.cnblogs.com/alva-rabbit-hole/p/10086939.html

超時重傳
上一篇文章裡介紹過TCP採用停止等待協議,即在收到接收方的確認資訊後才繼續傳送下面的資料。
那麼如果(在一段時間內)傳送方沒有收到確認資訊,我們便可以認為資料在傳輸的過程中出了差錯,沒有順利傳送到接收方。這種情況下,就需要一個“超時重傳”的機制了。

TCP 每傳送一個報文段,就對這個報文段設定一次計時器。只要計時器設定的重傳時間到但還沒有收到確認,就要重傳這一報文段。

那麼如何確定重傳時間呢?這是TCP最複雜的問題之一。

如果把超時重傳時間設定得太短,就會引起很多報文段的不必要的重傳,使網路負荷增大。
但若把超時重傳時間設定得過長,則又使網路的空閒時間增大,降低了傳輸效率。
為了得到較為合理的重傳時間,TCP 採用了一種自適應演算法。
超時重傳RTO演算法

該演算法中最關鍵的就是往返時間(RTT)的測量。
測量往返時間時,由於有的報文經過重傳後,無法判斷收到的確認報文是重傳報文的確認報文還是原報文的確認報文,故採用了Karn演算法:

在計算平均往返時間 RTT 時,只要報文段重傳了,就不採用其往返時間樣本。
報文段每重傳一次,就把 RTO 增大一些,以彌補重傳時間的無法更新。
擁塞控制
在研究擁塞控制的機制前,我們首先需要對“擁塞”的概念有所瞭解。

擁塞控制的基本概念
什麼是“擁塞”
在某段時間,若對網路中某資源的需求超過了該資源所能提供的可用部分,網路的效能就要變壞。這種現象稱為擁塞 (congestion)。
若網路中有許多資源同時產生擁塞,網路的效能就要明顯變壞,整個網路的吞吐量將隨輸入負荷的增大而下降。

“擁塞控制”與“流量控制”的區別
擁塞控制就是防止過多的資料注入到網路中,使網路中的路由器或鏈路不致過載;而流量控制往往指點對點通訊量的控制,是個端到端的問題(接收端控制傳送端)。
擁塞控制是一個全域性性的過程,涉及到所有的主機、所有的路由器,以及與降低網路傳輸效能有關的所有因素。
流量控制所要做的就是抑制傳送端傳送資料的速率,以便使接收端來得及接收。

利用擁塞視窗進行擁塞控制
TCP採用基於視窗的方法進行擁塞控制。
TCP傳送方維持一個“擁塞視窗”(congestion window),以控制端到端之間未確認的報文數量(擁塞的程度)。

這和之前提到的用於流量控制的“滑動視窗”很像,但是和由接受方決定的“滑動視窗”大小不同,“擁塞視窗”的大小是由傳送方決定的。

傳送視窗大小不僅取決於接收方公告的接收視窗,還取決於網路的擁塞狀況。
真正的傳送視窗值為:Min(公告視窗值,擁塞視窗值)

對於擁塞的判斷
1、重傳定時器超時
由於因傳輸出差錯而丟棄分組的概率是很小的(遠小於1%),所以只要出現了超時,就可以猜想網路可能出現了擁塞。

2、收到三個相同的ACK(3 duplicate ACKs)

先假設這麼一種情況,B等待A傳送首位元組序號為3的報文段,給A傳送“ack = 3”的確認報文段(ACK),而A在傳送過程中出現了丟失,B收到的只有4、5位元組的報文段;
此時B給A傳送的確認報文中ack欄位仍然等於3(因為位元組3還沒收到);
接著,在B收到位元組6後,給A傳送的確認報文仍然是“ack = 3”
這就是“收到三個相同ACK”的場景。

因此我們知道,“收到三個相同的ACK”說明有個別報文段在網路中丟失了,預示著網路狀況不好,可能會出現擁塞,需要採取措施避免擁塞。

擁塞控制演算法
擁塞控制是個麻煩事兒,相關的演算法也不少。或者說,多到讓人有些頭大。
有13種擁塞控制演算法

不過不用擔心,我們這裡只介紹在RFC 5681檔案中定義的四種互相緊密關聯的演算法:

慢開始(Slow Start)
擁塞避免(Congestion Aviudance)
快重傳(Fast Reyransmit)
快恢復(Fast Recovery)
下面的這張圖是一個擁塞控制的過程示例,在學習每一個部分的時候,可以對應圖中相應的部分理解。
擁塞控制

慢開始
雖然叫“慢開始”,但是它的擁塞視窗(cwnd)增長的速度可一點也不“慢”。
使用慢開始演算法後,每收到一個ACK,視窗值就加一;也就是意味著,每經過一個往返時間RTT,擁塞視窗cwnd就加倍。

這裡的一個“往返時間”指把擁塞視窗 cwnd 所允許傳送的報文段都連續傳送出去,並收到了對已傳送的最後一個位元組的確認。

慢開始門限 ssthresh(Slow Start Threshold)
慢開始門限相當於慢開始“指數式增長”的一個閾值。

當 cwnd < ssthresh 時,使用慢開始演算法。
當 cwnd > ssthresh 時,停止使用慢開始演算法而改用擁塞避免演算法。
當 cwnd = ssthresh 時,既可使用慢開始演算法,也可使用擁塞避免演算法。
擁塞避免
擁塞避免的設計思路是讓擁塞視窗的增長“慢下來”(相對於慢開始),呈線性增長,或者叫“加法增大”(Additive Increase)。

出現擁塞時
當發現網路出現擁塞時(重傳定時器超時),進行以下操作:

ssthresh = max(cwnd/2,2)
cwnd = 1
執行慢開始演算法
快重傳和快恢復
就是傳送方一連收到 3 個對同一個報文段的重複確認(3-ACK)時,傳送方執行快重傳和快恢復演算法。

快重傳(Fast Retransmission)
傳送方只要一連收到三個重複確認,就知道接收方確實沒有收到報文段,因而立即進行重傳(即“快重傳”),這樣就不會出現超時,傳送方也不就會誤認為出現了網路擁塞。
快重傳並非取消重傳計時器,而是在某些情況下可更早地重傳丟失的報文段。

快恢復(Fast Recovery)

ssthresh = cwnd/2
cwnd = ssthresh
執行擁塞避免演算法

可以留意一下“快恢復”與發現網路出現擁塞時(重傳定時器超時)的“‘慢’恢復”的區別。

加法增大,乘法減小(AIMD)
加法增大:擁塞避免階段,擁塞視窗按照線性規律增大;
乘法減小:當出現超時或3個重複的確認時,就要把門限值設定為當前擁塞視窗值的一半,並大大減小擁塞視窗的數值。
二者的結合就是所謂的AIMD演算法。

【後記】
擁塞控制的演算法這裡只介紹了較為常用的4種,更詳細的內容維基百科--TCP congestion control講得也比較清楚。
接下來的兩週可能會比較忙,沒有辦法更新部落格了。最近對3B1B的動畫引擎比較感興趣,可能會寫一些相關的內容。
最後,每一條留言都是我的動力(提前祝大家聖誕快樂了