深入理解TCP(二)


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

1、慢啟動

   當一條TCP連接開始時,cwnd的值一般初始設置為MSS的較小值。因為只有當發送方接收到ACK,才會更新cwnd的值,所以在一個RTT時間內,發送方只能發送cwnd字節大小的數據,這就使得初始發送速率大約為MSS/RTT。這是一個較小的值,大部分的帶寬還是空閑的,如何迅速更新cwnd以提高帶寬利用率??

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

  • 剛開始在第一個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,但是在慢啟動的過程中是以指數增長的。當然,帶寬是有限的,發送速率不可能無限制地增長,那么問題來了,什么時候結束這種指數增長??

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

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

    (3) 如果在慢啟動的過程中,發送方收到3個冗余的ACK,TCP就結束慢啟動過程,執行快速重傳並進入快速恢復模式

2、擁塞避免

   上面說到,只有當再次啟動慢啟動並且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進入快速恢復模式

3、快速恢復

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

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

  TCP的擁塞控制其實是加性增、乘性減(AIMD)的擁塞控制方式,當TCP連接的路徑上沒有擁塞(通過判斷丟包事件)時,發送速率加性增;當出現丟包事件時,發送速率乘性遞減。我們知道UDP本身是沒有實現擁塞控制的,其實如果大量使用UDP而沒有任何約束,那么網絡就很容易出現死鎖,使得端到端之間很少有數據能夠被傳輸。

4、總結:

  當然,雖然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很全面,可以給上層提高可靠的數據傳輸和各種機制。到底選擇哪一種傳輸層協議,其實還要根據具體的應用來選擇。存在既有價值,關鍵是各方面的權衡而已。

版權所有,歡迎轉載,轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM