【TCP】可靠數據傳輸


TCP可靠數據傳輸

  在TCP在IP不可靠的盡力而為的服務之上,創建了一條可靠數據傳輸服務(reliable data transfer service)
TCP提供的可靠數據傳輸的方法涉及到可靠數據傳輸原理中許多機制。
  也涉及到了定時器。如果為每一個已發送但未被確認的報文段都設置一個定時器,那開銷是相當巨大的。因此
推薦的定時器管理過程[RFC 6298]僅適用單一的重傳定時器。下面描述的TCP協議遵從了這種單一的定時器推薦。

  TCP是使用超時冗余確認技術來恢復報文段的丟失

TCP發送方有3個與發送和重傳有關的事件

  • 從上層應用程序接收數據
    TCP從應用程序接收數據,將數據封裝在一個報文段中(含有第一個數據字節的流編號),然后交給IP。

  • 定時器超時
    超時后,TCP重傳超時報文,然后,重啟定時器。

  • 收到ACK
    收到ACK后,將確認報文中確認號與發送方的SendBase(最早未被確認的字節序號)比較。
    TCP采取累積確認,所以確認號之前的字節都被接收方收到。
    當 確認號 > SendBase 時,則該ACK是在確認一個或多個先前未被確認的報文段,此時發送方更新
    SendBase的值
    如果當前有未被確認的報文段,TCP重啟定時器

TCP協議在工作過程中的幾種簡單情況

1.由於確認丟失而重傳

      

  如上圖所示,B發送給A的ACK丟失,引起了主機A的重傳,B在接收到重傳數據報后根據序號得知這是重傳報文,於是丟棄該報文,向A發送ACK。

2.連續發送的報文段的ACK延遲

      

  A連續向B發送了兩個報文段,但是他們的ACK都延遲了,導致定時器超時,於是最早的未被確認的報文段92被重
傳,接着他們的ACK到達,它們就不會被再次重傳,A收到確認后,就會將SendBase后移,並重啟定時器。

3.累積確認避免先前報文段重傳

      

  A還是向B連續發送了兩個報文段,但是第一個報文段的ACK丟失啦。但是好的是在定時器超時之前,第二個報文
段的ACK到達,因為TCP采取了累計確認,第二個報文段ACK到達,說明了第一個報文段是被正確接收了噠。所以第一個報文段不會被重傳。

快速重傳

  超時重傳存在的問題之一就是超時周期可能較長。當一個報文段丟失時,通過超時重傳來恢復報文,就會增加端
到端的時延。Luckily,可以通過檢測收到的冗余ACK來進行對丟失報文段的重傳。


  至於為啥可以通過這樣的方式來確信此報文段丟失是因為:
  ①發送方接到丟失報文段后的報文(也就是失序報文段)會將失序報文段緩存,並向發送方發送最近接收的未失
  序報文段的最大編號。
  ②如果接收方連續接收多個失序報文,那么發送方將會收到對一個報文段的多個ACK,由此發送方可知該ACK代
  表的報文段的后一個報文丟失了,於是,發送方重傳丟失報文。

  當發送方收到3個冗余ACK,就說明被確認過三次的報文段之后的那個報文段已經丟失,TCP就執行快重傳
  (fast retransmit),在丟失報文段定時器超時之前重傳丟失報文段。

      

              上圖是快重傳的一個示例

是回退N步還是選擇重傳

  根據前面對TCP描述,可以得知TCP確認是采用累積確認方式,並且對失序報文不會給出確。這讓TCP看起來像是一個GBN協議,但是與GBN不同的是,TCP會緩存失序的分組。所以,TCP提出的一種修改意見是選擇確認(slective acknowledgment)[RFC 2018],它允許TCP接收方有選擇地確認失序報文段,而不是累積確認最后一個正確接收的有序報文段。當將該機制和選擇重傳機制結合起來使用時(即跳過重傳那些已被接收方選擇確認過的報文段),TCP就像我們通常的SR協議。

  因此,TCP的差錯恢復機制為GBN協議和SR協議的混合體。

TCP流量控制

為什么要提供流量控制服務(flow-control service)?

  簡單地說,提供流控就是為了避免接收方緩存溢出問題。

  接收方接收到數據后,會將其放入接收緩存中,待上層應用程序讀取數據。但是上層應用可能忙於其他事務或者
  讀取數據的速度比較慢,而發送方發送數據的太多,速率太快,此時就會導致接收方的緩存溢出。
  流量控制也是一個速率匹配服務。

  TCP的發送方也可能會因為IP網絡擁塞而被遏制,這種形式的控制被稱為擁塞控制(congestion control)。這兩
  種控制是針對不同原因而采取的,盡管他們都是對發送方的遏制。后面會講他們之間的區別。

TCP如何提供流量控制服務 ?

  這里為了從整體上看問題,我們假設,TCP接收方會丟棄失序的報文。

  1. TCP讓發送方A維護一個稱為接收窗口(receive window)的變量來提供流量控制。這個窗口代表接收方B有多少可的緩存空間
  2. 主機A和主機B之間建立TCP連接后,主機B為連接分配了一個接收緩存,用RcvBuffer表示
    定義如下變量
  • LastByteRead:主機B的應用進程從緩存中取出的數據流最后一個字節的編號
  • LastByteRevd:主機B緩存的數據流的最后一個字節編號


緩存不能溢出需滿足

                         LastByteRevd - LastByteRead <= RevBuffer


接收窗口rwnd根據緩存可用空間設置:

                        rwnd = RevBuffer - [LastByteRevd-LastByteRead]

3. 主機B通過把當前的rwnd放到它發送給主機A的報文段的 接收窗口字段,已通知主機A當前它還有多少空間可用。 4. 主機A始終跟蹤兩個LastByteSend和LastByteAcked,[LastByteSend-LastByteAcked]就是主機A中發送但未被確認的數據量。使這個值小於主機B的rwnd,就可以使主機B的緩存不會溢出。
因此,主機A需要在連接的整個生命周期滿足: ``` LastByteSend-LastByteAcked <= rwnd ```
如何防止死鎖?

死鎖問題出現
  主機B的接收緩存滿了,rwnd=0。主機A知道了就會暫停數據發送,等待主機B的接收緩存有空閑。如果此時主機B沒有數據發送給A那么A將不可能知道主機B會有緩存空閑,這會導致A被阻塞(主機B僅當他有數據發送或者有確認時才會發送報文段給A) !

解決死鎖問題
  當發送方A收到接收方B的窗口為0的通知,便啟動一個一個持續計數器,每隔一段時間向B發送只有一個字節數據的零窗口探測報文段。這些報文段將被接收方確認。最終緩存將開始清空,並且確認報文里包含一個非0的rwnd值。


  此文為《計算機網絡 自頂向下方法》的學習筆記5,文中圖來自本書。


免責聲明!

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



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