1. 程式人生 > >計算機網絡【7】—— TCP的精髓

計算機網絡【7】—— TCP的精髓

每次 大量 一半 想想 了解 重傳 tro https res

參考文獻:

http://blog.chinaunix.net/uid-26275986-id-4109679.html

TCP協議作為一個可靠的面向流的傳輸協議,其可靠性和流量控制由滑動窗口協議保證,而擁塞控制則由控制窗口結合一系列的控制算法實現。

一、滑動窗口協議

關於這部分自己不曉得怎麽敘述才好,因為理解的部分更多,下面就用自己的理解來介紹下TCP的精髓:滑動窗口協議

所謂滑動窗口協議,自己理解有兩點:1. “窗口”對應的是一段可以被發送者發送的字節序列,其連續的範圍稱之為“窗口”;2. “滑動”則是指這段“允許發送的範圍”是可以隨著發送的過程而變化的,方式就是按順序“滑動”。在引入一個例子來說這個協議之前,我覺得很有必要先了解以下前提:

  1. TCP協議的兩端分別為發送者A和接收者B,由於是全雙工協議,因此A和B應該分別維護著一個獨立的發送緩沖區和接收緩沖區,由於對等性(A發B收和B發A收),我們以A發送B接收的情況作為例子;
  2. 發送窗口是發送緩存中的一部分,是可以被TCP協議發送的那部分,其實應用層需要發送的所有數據都被放進了發送者的發送緩沖區;
  3. 發送窗口中相關的有四個概念:
    • 已發送並收到確認的數據(不再發送窗口和發送緩沖區之內)
    • 已發送但未收到確認的數據(位於發送窗口之中)
    • 允許發送但尚未發送的數據
    • 發送窗口外發送緩沖區內暫時不允許發送的數據;

  4. 每次成功發送數據之後,發送窗口就會在發送緩沖區中按順序移動,將新的數據包含到窗口中準備發送;

TCP建立連接的初始,B會告訴A自己的接收窗口大小,比如為‘20’:

字節31-50為發送窗口

技術分享圖片
A發送11個字節後,發送窗口位置不變,B接收到了亂序的數據分組:
技術分享圖片
只有當A成功發送了數據,即發送的數據得到了B的確認之後,才會移動滑動窗口離開已發送的數據;同時B則確認連續的數據分組,對於亂序的分組則先接收下來,避免網絡重復傳遞:
技術分享圖片

二、流量控制

流量控制方面主要有兩個要點需要掌握。一是TCP利用滑動窗口實現流量控制的機制;二是如何考慮流量控制中的傳輸效率

1. 流量控制

所謂流量控制,主要是接收方傳遞信息給發送方,使其不要發送數據太快,是一種端到端的控制。主要的方式就是返回的ACK中會包含自己的接收窗口的大小,並且利用大小來控制發送方的數據發送:
技術分享圖片
這裏面涉及到一種情況,如果B已經告訴A自己的緩沖區已滿,於是A停止發送數據;等待一段時間後,B的緩沖區出現了富余,於是給A發送報文告訴A我的rwnd大小為400,但是這個報文不幸丟失了,於是就出現A等待B的通知||B等待A發送數據的死鎖狀態。為了處理這種問題,TCP引入了持續計時器(Persistence timer),當A收到對方的零窗口通知時,就啟用該計時器,時間到則發送一個1字節的探測報文,對方會在此時回應自身的接收窗口大小,如果結果仍未0,則重設持續計時器,繼續等待。

2. 傳遞效率

一個顯而易見的問題是:單個發送字節單個確認,和窗口有一個空余即通知發送方發送一個字節,無疑增加了網絡中的許多不必要的報文(請想想為了一個字節數據而添加的40字節頭部吧!),所以我們的原則是盡可能一次多發送幾個字節,或者窗口空余較多的時候通知發送方一次發送多個字節。對於前者我們廣泛使用Nagle算法,即:
*1. 若發送應用進程要把發送的數據逐個字節地送到TCP的發送緩存,則發送方就把第一個數據字節先發送出去,把後面的字節先緩存起來;
*2. 當發送方收到第一個字節的確認後(也得到了網絡情況和對方的接收窗口大小),再把緩沖區的剩余字節組成合適大小的報文發送出去;
*3. 當到達的數據已達到發送窗口大小的一半或以達到報文段的最大長度時,就立即發送一個報文段;
對於後者我們往往的做法是讓接收方等待一段時間,或者接收方獲得足夠的空間容納一個報文段或者等到接受緩存有一半空閑的時候,再通知發送方發送數據。

三、擁塞控制

網絡中的鏈路容量和交換結點中的緩存和處理機都有著工作的極限,當網絡的需求超過它們的工作極限時,就出現了擁塞。擁塞控制就是防止過多的數據註入到網絡中,這樣可以使網絡中的路由器或鏈路不致過載。常用的方法就是:
  、擁塞控制快重傳、快恢復 )
一切的基礎還是慢開始,這種方法的思路是這樣的:
-1. 發送方維持一個叫做“擁塞窗口”的變量,該變量和接收端口共同決定了發送者的發送窗口;
-2. 當主機開始發送數據時,避免一下子將大量字節註入到網絡,造成或者增加擁塞,選擇發送一個1字節的試探報文;
-3. 當收到第一個字節的數據的確認後,就發送2個字節的報文;
-4. 若再次收到2個字節的確認,則發送4個字節,依次遞增2的指數級;
-5. 最後會達到一個提前預設的“慢開始門限”,比如24,即一次發送了24個分組,此時遵循下面的條件判定:
  *1. cwnd < ssthresh, 繼續使用慢開始算法;
  *2. cwnd > ssthresh,停止使用慢開始算法,改用擁塞避免算法;
  *3. cwnd = ssthresh,既可以使用慢開始算法,也可以使用擁塞避免算法;
-6. 所謂擁塞避免算法就是:每經過一個往返時間RTT就把發送方的擁塞窗口+1,即讓擁塞窗口緩慢地增大,按照線性規律增長;
-7. 當出現網絡擁塞,比如丟包時,將慢開始門限設為原先的一半,然後將cwnd設為1,執行慢開始算法(較低的起點,指數級增長);
技術分享圖片
上述方法的目的是在擁塞發生時循序減少主機發送到網絡中的分組數,使得發生擁塞的路由器有足夠的時間把隊列中積壓的分組處理完畢。慢開始和擁塞控制算法常常作為一個整體使用,而快重傳和快恢復則是為了減少因為擁塞導致的數據包丟失帶來的重傳時間,從而避免傳遞無用的數據到網絡。快重傳的機制是:
-1. 接收方建立這樣的機制,如果一個包丟失,則對後續的包繼續發送針對該包的重傳請求;
-2. 一旦發送方接收到三個一樣的確認,就知道該包之後出現了錯誤,立刻重傳該包;
-3. 此時發送方開始執行“快恢復”算法:
*1. 慢開始門限減半;
*2. cwnd設為慢開始門限減半後的數值;
*3. 執行擁塞避免算法(高起點,線性增長);
技術分享圖片

四、可靠傳輸的停止等待協議和連續ARQ協議

網絡傳輸的理想傳輸狀態就是:

1、傳輸信道不產生差錯。

2、不管發送方以多塊的速度發送數據,接收方都能來得及接受以及處理這些數據。

當然,這種只是理想狀態,在實際運用中,幾乎是不可能的。因此,我們需要采取一些可靠的傳輸協議。

1、當出現差錯時,讓發送發重傳該差錯數據。

2、接受方來不及處理數據時,及時告知發送方適當的降低發送速度。

那麽,要做到上述第一點,就需要采用:停止等待協議

1. 停止等待協議

所謂停止等待協議就是沒發送完一組數據後,等待對方確認並且收到確認後,再發送下一組數據。

我將它簡單的理解為以下過程:發送數據,收到數據,發送確認,收到確認。

那麽這樣,就分為了以下4種情況。(無差錯、出現差錯、確認丟失、確認遲到)

1、無差錯

技術分享圖片

所謂無差錯,就是數據能夠正常發送,正常接收,正常確認,正常收到確認的一個過程。也是最理想,最好的一種狀態。

2、出現差錯

技術分享圖片

所謂出現差錯,就是數據在發送的過程中部分或全部丟失(如上圖左)。

A發送M1並出現差錯,B在收到M1時(全部丟失,不會收到)檢測出了差錯,就丟棄M1,其他什麽也不做(不會通知A數據出現了差錯,因為有可能全部丟失,B並不知道)。在這兩種情況下,B都不會發送任何的信息。那麽,怎麽辦?

A只要超過一段時間仍然沒有收到確認,就認為剛才所發送的數據丟失,然後重傳前面發送的數據。這就叫做超時重傳。當前需要一個計時器來完成。

因此,有如下三點要求:

1>、A在發送完一組數據後,必須暫時保留自己已發送的數據的副本(供超時重傳使用)。只有收到確認後,才會刪除該副本。

2>、每一組數據和確認數據都必須編號(TCP頭部有該字段)。這樣才能明確是哪一個發送出去的數據收到了確認,哪一個沒有收到。

3>、超時計時器設定的時間應該要長於數據平均往返時間。

3、確認丟失

技術分享圖片

所謂確認丟失,其實就是確認消息在傳輸過程丟失。那麽,該如何處理?

當A發送M1消息,B收到後,B向A發送了一個M1確認消息,但卻在傳輸過程中丟失。而A並不知道,在超時計時過後,A重傳M1消息,B再次收到該消息後采取以下兩點措施:

1>、丟棄這個重復的M1消息,不向上層交付。

2>、向A發送確認消息。(不會認為已經發送過了,就不再發送。A能重傳,就證明B的確認消息丟失)。

4、確認遲到

技術分享圖片

所謂確認遲到,就是B發送的確認消息沒有丟失,但是卻遲到(過了很長一段時間才到)。那麽該如何處理?

A發送M1消息,B收到並發送確認。在超時時間內沒有收到確認消息,A重傳M1消息,B仍然收到並繼續發送確認消息(B收到了2份M1)。此時A收到了B第二次發送的確認消息。接著發送其他數據。過了一會,A收到了B第一次發送的對M1的確認消息(A也收到了2份確認消息)。處理如下:

1>、A收到重復的確認後,直接丟棄。

2>、B收到重復的M1後,也直接丟棄重復的M1。

至此,就是停止等待協議中所出現的所有的可能情況。也一一解決。像這種可靠的傳輸協議通常稱為自動重傳請求ARQ(Automatic Repeat reQuest)。意思就是,重傳的請求是自動進行的,不需要接受方請求發送某一個丟失或出錯的消息。

但是,很顯然。我們發現,其信道的利用率很低。

那該怎麽辦?

那就是利用連續ARQ請求協議。

2. 連續ARQ協議  

先看一張信道利用率圖:

技術分享圖片

這兩張圖的差異很明顯。使用連續的ARQ協議可以大大的提高信道利用率。

吧後者這張圖的工作模式又叫做流水線傳輸。

其原理如下:

技術分享圖片

其實現的基礎是建立在滑動窗口之上。而滑動窗口乃是TCP的精髓所在(下一篇詳解)。

連續ARQ規定,發送方每收到一個確認就將滑動窗口向前(時間增大方向)滑動一格。如上圖表示收到一個確認。

接受方采用累積確認的方式:接收方不必每收到一個消息,就發送一個確認。而是在收到幾條消息後,對按序到達的最後一條消息發送確認。表示,這個消息之前的所有消息全部收到。

當然,這兩個方式都有自己的優缺點:

1、自動重傳請求ARQ協議

優點:簡單

缺點:信道利用率低

2、連續的ARQ協議

優點:信道利用率高,容易實現,即使確認丟失,也不必重傳。

缺點:不能向發送方反映出接收方已經正確收到的所有分組的信息。

比如:發送方發送了5條消息,中間第三條丟失(3號),這時接收方只能對前兩個發送確認。發送方無法知道後三個分組的下落,而只好把後三個全部重傳一次。這也叫

Go-Back-N(回退N),表示需要退回來重傳已經發送過的N個消息。

計算機網絡【7】—— TCP的精髓