深刻理解TCP(二)

   上一篇http://www.cnblogs.com/whc-uestc/p/4715334.html中已經講到TCP跟蹤一個擁塞窗口來(cwnd)提供擁塞控制服務,經過調節cwnd值以控制發送速率。那麼TCP如何基於丟包事件來設置cwnd值?經過TCP擁塞控制算法來實現。TCP擁塞控制算法主要有三部分:慢啓動、擁塞避免、快速恢復。html

一、慢啓動算法

   當一條TCP鏈接開始時,cwnd的值通常初始設置爲MSS的較小值。由於只有當發送方接收到ACK,纔會更新cwnd的值,因此在一個RTT時間內,發送方只能發送cwnd字節大小的數據,這就使得初始發送速率大約爲MSS/RTT。這是一個較小的值,大部分的帶寬仍是空閒的,如何迅速更新cwnd以提升帶寬利用率??網絡

  慢啓動狀態:cwnd的值以1個MSS開始而且每當傳輸的報文段首次被確認就增長一個MSS。spa

  • 剛開始在第一個RTT中,cwnd只有1個MSS,發送一個報文;
  • 收到一個ACK,此時cwnd增長1個MSS,在第2個RTT,cwnd爲2個MSS,發送兩個報文;
  • 會收到兩個ACK,此時cwnd增長2個MSS,因此在第3個RTT中,cwnd爲4個MSS,發送4個報文;
  • 依次類推。

  從上面的過程,不難發現每過一個RTT,發送速率就會翻一倍。雖然起始速率只有MSS/RTT,可是在慢啓動的過程當中是以指數增加的。固然,帶寬是有限的,發送速率不可能無限制地增加,那麼問題來了,何時結束這種指數增加??htm

  (1) 當有一個超時引發的丟包事件(擁塞)時,TCP發送方將cwnd設置爲1並從新開始慢啓動過程;同時將慢啓動閾值ssthresh設置爲cwnd/2。blog

  (2) 在(1)從新慢啓動過程當中,當cwnd的值增加到大於等於慢啓動閾值ssthresh時,慢啓動結束,同時轉移到擁塞避免模式排序

    (3) 若是在慢啓動的過程當中,發送方收到3個冗餘的ACK,TCP就結束慢啓動過程,執行快速重傳並進入快速恢復模式事件

二、擁塞避免get

   上面說到,只有當再次啓動慢啓動而且cwnd增加到大於等於慢啓動閾值ssthresh時,纔會進入擁塞避免模式,因此當進入到擁塞避免時,cwnd的值大概是在第一次遇到擁塞時的cwnd的值的一半。此時若是繼續進行慢啓動就會使cwnd的值翻倍從而可能致使擁塞。因此擁塞避免模式對於每次收到的ACK,並不像慢啓動那樣直接將cwnd增長一個MSS字節,而是增長MSS*MSS/cwnd字節。也就是說當MSS=1460字節,cwnd爲14600字節,那麼每次收到一個ACK,cwnd增長1460*1/10字節,只有收到10個ACK,cwnd纔會增長一個MSS。總結

  問題來了,與慢啓動同樣,難道cwnd的值也是這麼一直增加下去麼??何時結束呢?

  (1) 當有一個超時引發的丟包事件(擁塞)時,同慢啓動同樣,TCP發送方將cwnd設置爲1並從新開始慢啓動過程;同時將ssthresh設置爲cwnd/2。

    (2) 當收到3個冗餘的ACK時,ssthresh設置爲cwnd/2,TCP將cwnd的值設置爲ssthresh+3進入快速恢復模式

三、快速恢復

  對於引發TCP進入快速恢復狀態的缺失報文段,對收到的每一個冗餘ACK,cwnd的值增長1個MSS,當收到新的ACK時TCP把cwnd設置爲ssthresh的值進入擁塞避免狀態

  當在快速恢復階段出現超時事件,cwnd的值被設置爲1個MSS,而且ssthresh的值設置爲cwnd的一半,進入慢啓動狀態

  TCP的擁塞控制實際上是加性增、乘性減(AIMD)的擁塞控制方式,當TCP鏈接的路徑上沒有擁塞(經過判斷丟包事件)時,發送速率加性增;當出現丟包事件時,發送速率乘性遞減。咱們知道UDP自己是沒有實現擁塞控制的,其實若是大量使用UDP而沒有任何約束,那麼網絡就很容易出現死鎖,使得端到端之間不多有數據可以被傳輸。

四、總結:

  固然,雖然UDP是不可靠、無鏈接的傳輸層協議,而TCP是面向鏈接的提供可靠數據傳輸的傳輸層協議。可是UDP的應用依舊很廣,像DNS,QQ都是用的是UDP,不少人會奇怪,爲何TCP提供了那麼多服務,爲何不用TCP而用這麼不可靠的UDP呢??

  其實不管TCP仍是UDP,在如此複雜的網絡中,並不多是徹底可靠的。

  • TCP只是經過確認和重傳機制來保證它的可靠性,而UDP並無確認和重傳機制。
  • TCP提供有序的數據流服務,UDP每一個數據包是單獨的,在接收方並不保證提交給應用層的數據包是有序的。
  • TCP提供流量控制和擁塞控制,經過流量控制,可讓發送方和接收方的應用層從接收緩衝區讀取數據的速率匹配,從而不會由於接收緩衝區滿而發生丟包;經過擁塞控制,每個經過擁塞鏈路的TCP鏈接都可以平等地共享鏈路帶寬。

  可是正由於TCP提供了這麼多的服務,使得TCP變得很臃腫,很難發送大容量的數據;這時候,輕量的傳輸層協議UDP就站出來了。UDP很簡單,不提供那麼多的機制和服務,使得UDP的傳輸速率能夠比TCP快不少。固然有人會說,UDP丟包率很高,UDP接收到無序的數據包,UDP沒有擁塞,可能致使網絡癱瘓等等一些問題。

  由於傳輸層及以上的層次都是隻在端系統中實現的,在網絡分組交換機中只有網絡層一下的實現,也就是說TCP的全部這些服務都是基於端到端的服務。既然是端到端的服務,那麼上述的全部問題均可以經過上層(也就是應用層)來實現,經過在應用層把發送的數據進行編號,就能夠在接收端對接收的數據進行排序,從而的到有序的數據;經過在應用層添加確認和重傳,就能夠大大下降丟包率;經過在應用層加一個窗口,來達到流量控制和擁塞控制的目的。固然具體基於UDP的實現其實並不須要把因此TCP的服務都在應用層實現,不然還不如用TCP。咱們只須要實現那些咱們須要和關係的服務便可,好比說咱們須要下降丟包率,咱們就只實現重傳機制。(固然咱們也能夠徹底不用傳輸層,應用層直接經過網絡層通訊)

  UDP很自由,能夠任由上層來實現;TCP很全面,能夠給上層提升可靠的數據傳輸和各類機制。到底選擇哪種傳輸層協議,其實還要根據具體的應用來選擇。存在既有價值,關鍵是各方面的權衡而已。

版權全部,歡迎轉載,轉載請註明出處。

相關文章
相關標籤/搜索