1. 程式人生 > >TCP的超時重傳機制與擁塞避免

TCP的超時重傳機制與擁塞避免

TCP超時與重傳機制
  
  TCP協議是一種面向連線的可靠的傳輸層協議,它保證了資料的可靠傳輸,對於一些出錯,超時丟包等問題TCP設計的超時與重傳機制。其基本原理:在傳送一個數據之後,就開啟一個定時器,若是在這個時間內沒有收到傳送資料的ACK確認報文,則對該報文進行重傳,在達到一定次數還沒有成功時放棄併發送一個復位訊號。
  這裡比較重要的是重傳超時時間,怎樣設定這個定時器的時間(RTO),從而保證對網路資源最小的浪費。因為若RTO太小,可能有些報文只是遇到擁堵或網路不好延遲較大而已,這樣就會造成不必要的重傳。太大的話,使傳送端需要等待過長的時間才能發現數據丟失,影響網路傳輸效率。
  由於不同的網路情況不一樣,不可能設定一樣的RTO,實際中RTO是根據網路中的RTT(傳輸往返時間)來自適應調整的。具體關係參考相關演算法。
  通過圖來了解重傳機制:
 這裡寫圖片描述

從圖可以知道,傳送方連續傳送3個數據包,其中第二個丟失,沒有被接收到,因此不會返回對應的ACK,沒傳送一個數據包,就啟動一個定時器,當第二個包的定時器溢位了還沒有收到ack,這時就進行重傳。

TCP慢啟動

  慢啟動是TCP的一個擁塞控制機制,慢啟動演算法的基本思想是當TCP開始在一個網路中傳輸資料或發現數據丟失並開始重發時,首先慢慢的對網路實際容量進行試探,避免由於傳送了過量的資料而導致阻塞。
  慢啟動為傳送方的TCP增加了另一個視窗:擁塞視窗(congestion window),記為cwnd。當與另一個網路的主機建立TCP連線時,擁塞視窗被初始化為 1個報文段(即另一端通告的報文段大小)。每收到一個ACK,擁塞視窗就增加一個報文段(cwnd以位元組為單位,但是慢啟動以報文段大小為單位進行增加)。傳送方取擁塞視窗與通告視窗中的最小值作為傳送上限。擁塞視窗是傳送方使用的流量控制,而通告視窗則是接收方使用的流量控制。傳送方開始時傳送一個報文段,然後等待 ACK。當收到該ACK時,擁塞視窗從1增加為2,即可以傳送兩個報文段。當收到這兩個報文段的 A C K時,擁塞視窗就增加為4。這是一種指數增加的關係。

擁塞避免演算法

  網路中擁塞的發生會導致資料分組丟失,需要儘量避免。在實際中,擁塞演算法與慢啟動通常在一起實現,其基本過程:
   1. 對一個給定的連線,初始化cwnd為1個報文段,ssthresh為65535個位元組。
   2. TCP輸出例程的輸出不能超過cwnd和接收方通告視窗的大小。擁塞避免是傳送方使用 的流量控制,而通告視窗則是接收方進行的流量控制。前者是傳送方感受到的網路擁塞的估 計,而後者則與接收方在該連線上的可用快取大小有關。
   3. 當擁塞發生時(超時或收到重複確認),ssthresh被設定為當前視窗大小的一半(cwnd 和接收方通告視窗大小的最小值,但最少為2個報文段)。此外,如果是超時引起了擁塞,則 cwnd被設定為1個報文段(這就是慢啟動)。
   4. 當新的資料被對方確認時,就增加cwnd,但增加的方法依賴於是否正在進行慢啟動或擁塞避免。如果cwnd小於或等於ssthresh,則正 在進行慢啟動,否則正在進行擁塞避免。慢啟動一直持續到回到當擁塞發生時所處位置的半時候才停止(因為記錄了在步驟2 中製造麻煩的視窗大小的一半),然後轉為執行擁塞避免。
   慢啟動演算法初始設定cwnd為1個報文段,此後每收到一個確認就加 1。那樣,這會使視窗按指數方式增長:傳送 1個報文段,然後是2個,接著是4個……。

這裡寫圖片描述

  在該圖中,假定當cwnd為32個報文段時就會發生擁塞。於是設定 ssthresh為16個報文段,而cwnd為1個報文段。在時刻 0傳送了一個報文段,並假定在時刻 1接收到它的ACK,此時cwnd增加為2。接著傳送了2個報文段,並假定在時刻 2接收到它們的ACK,於是cwnd增加為4(對每個ACK增加1次)。這種指數增加演算法一直進行到在時刻3和4之間收到8個ACK後cwnd等於ssthresh時才停止,從該時刻起,cwnd以線性方式增加,在每個往返時間內最多增加 1個報文段。

快速重傳和快速恢復演算法

  這是資料丟包的情況下給出的一種修補機制。一般來說,重傳發生在超時之後,但是如果傳送端接受到3個以上的重複ACK的情況下(上面的圖中第二個包丟失了,就收到了兩個相同的ack=11),就應該意識到,資料丟了,需要重新傳遞。這個機制是不需要等到重傳定時器溢位的,所以叫做快速重傳,它可以避免傳送端因等待重傳計時器的超時而空閒較長時間,以此增加網路吞吐量。而重新傳遞以後,因為走的不是慢啟動而是擁塞避免演算法,所以這又叫做快速恢復演算法。演算法流程如下:
  1. 當收到第3個重複的ACK時,將ssthresh設定為當前擁塞視窗cwnd的一半。重傳丟失的報文段。設定cwnd為ssthresh加上3倍的報文段大小。
  2. 每次收到另一個重複的ACK時, cwnd增加1個報文段大小併發送1個分組(如果新的cwnd允許傳送)。
  3. 當下一個確認新資料的ACK到達時,設定cwnd為ssthresh(在第1步中設定的值)。這個 ACK應該是在進行重傳後的一個往返時間內對步驟1中重傳的確認。另外,這個ACK也應該是對丟失的分組和收到的第1個重複的ACK之間的所有中間報文段 的確認。
  

TCP成塊資料流