【計算機網絡】3.3 可靠數據傳輸原理

第三章第三節 可靠數據傳輸原理

  信道通常指鏈接信號發送方和接收方的傳輸線路,包括雙絞銅線等物理媒體。在實際的網絡傳輸中,信道是不可靠的,在其上傳輸的分組可能會損壞或丟失,甚至相對次序都不能保證。網絡

  TCP 這一 運輸層協議 則提供了可靠的數據傳輸框架解決上述問題,其向上層(應用層)提供面向鏈接的可靠的服務。而TCP的下層是網絡層,網絡層提供的盡力而爲的服務,也就是說不提供任何質量保證。簡單來講,TCP實現如下兩個功能,即「可靠」的概念:傳輸的數據比特不會受到損壞或丟失;全部數據都是按照其發送順序進行交付的。框架

  在本節中咱們僅討論單向數據傳輸(unidirectional data transfer)的狀況,介紹可靠傳輸協議、流水線協議、回退N步、選擇重傳。函數

Outline

Notes

## 可靠服務的模型

  • 上圖就說明了用於數據傳輸協議的各個接口。
    • 運輸層經過rdt_send()函數,調用數據傳輸協議的發送方,把數據交付給接收方的較高層。
    • 發送方的運輸層調用udt_send()函數,將分組發送到不可靠的信道。
    • 當分組從信道的接收端到達接收端時,將調用rdt_recv()
    • rdt協議向較高層交付數據時,調用deliver_data()

 

## 通過徹底可靠的信道的 rdt 1.0

  有限狀態機(FSM) 能夠表示有限個狀態及在這些狀態之間的轉移和動做等行爲的數學模型,下圖即表示發送方和接收方的有限狀態機,底層信道是徹底可靠的,發送方和接收方有各自的FSM,每一個FSM都只有一個狀態。性能

  (圖解:FSM描述中的箭頭指示了協議從一個狀態變遷到另外一個狀態。引發變遷的事件顯示在橫線的上方,事件發生時所採用的運動顯示在橫線的下方。FSM的初始狀態用虛線表示。)spa

 

  • 發送端,只經過 rdt_send(data) 事件接收來自較高層的數據發送請求。在完成一次數據發送請求中須要兩個動做:
    • 產生一個包含該數據的分組(經由 make_pkt(data) 產生)
    • 而後將該分組經過 udt_send(packet) 發送到信道中
  • 完成這兩個動做後,從新返回原始狀態,繼續等待來自較高層的數據發送請求。
  • 接收端,rdt 經過 rdt_rcv(packet) 事件從底層信道接收一個分組。在一次數據接收過程當中一樣須要兩個動做:
    • 從分組中取出數據(經由 extract(packet, data) 產生)
    • 而後將數據上傳給較高層(經過 deliver_data(data) 動做)
  • 和發送端同樣,接收端完成這兩個動做後也從新返回原始狀態,繼續等待從底層信道接收分組。
  • 值得注意的是,rdt的發送端是由較高層應用的調度產生的,接收端協議是由較底層協議的過程調度產生的
  • 在這個協議中,一個單元數據和一個分組沒有區別。
  • 由於信道可靠,接收方也不須要提供任何反饋信息給發送方
  • 假定了接收方接收數據的速率可以與發送方發送數據的速率同樣快,因此接收方也沒有必要請求發送方慢一點發送。

 

## 經有比特差錯信道的可靠數據傳輸: rdt2.0

  如今咱們能夠假設在信道傳輸過程當中分組中的比特可能受損了,在這種比特可能受損的狀況下,來看一下如何構造可靠數據傳輸協議 rdt 2.0。注意如今仍然假定全部發送的分組(即便受損)將按照其發送的順序被接收,同時信道中的分組也不會丟失。code

  接收方收到分組之後,能夠向發送方發送確定確認 (ACK) 或否認確認 (NAK) 。這些控制報文可讓發送方知道哪些內容被正確接收,哪些內容接收有誤並所以須要重複。這種基於重傳的可靠數據傳輸協議被稱爲自動重傳請求 (Automatic Repeat reQuest, ARQ) 協議blog

  ARQ協議須要三個功能來處理分組出錯的狀況:接口

  • 差錯檢測。咱們須要一種機制可以使接收方檢測何時出現了比特差錯。
    • 好比 UDP檢驗和 字段就是爲了這個目的。
    • 這些技術要求有額外的比特從發送方發送到接收方,而這些比特將存放在 rdt 2.0 數據分組的分組檢驗和 字段中。
  • 接收方反饋。發送方要了解接收方是否正確接收分組的惟一途徑就是讓接收方提供明確的反饋信息
    • rdt 2.0 協議將從接收方向發送方回送 ACK 或 NAK 分組。
    • 這些分組在理論上只須要一個比特長,好比用 0 表示 NAK,用 1 表示 ACK。
  • 重傳。若是接收方收到了受損的分組,發送方必須重傳該分組。

【rdt2.0 自動重傳請求協議】

  下圖爲rdt 2.0 的有限狀態機描述圖,該數據傳輸協議(自動重傳請求協議)採用了差錯檢測、確定確認與否認確認。事件

  • 在發送端左邊的初始狀態中,發送端協議正等待來自較高層傳下來的數據。當觸發 rdt_send(data) 事件時:
    • 經過 sndpkt = make_pkt(data, checksum) 產生一個包含待發送數據且帶有校驗和的分組
    • 而後將該分組經過 udt_send(sndpkt) 發送到信道中
  • 執行完上述的兩個動做後,發送端的狀態變遷爲「等待接收接收端的 ACK 或 NAK 分組」。即轉變爲右側狀態,接下來根據接收端的響應不一樣會有不一樣的變遷方案:
    • 若是收到了一個 ACK 分組(rdt_rcv(rcvpkt) && isACK(rcvpkt)),那麼發送方知道最近一個分組已經被正確接收,所以協議返回左邊狀態,繼續等待下一次由較高層傳下來的數據發送請求
    • 若是收到了一個 NAK 分組(rdt_rcv(rcvpkt) && isNAK(rcvpkt)),那麼發送端知道接收端接收到的分組是受損的,因此調用 udt_send(sndpkt) 從新發送該分組,而後狀態不變,繼續等待接收接收端的 ACK 或 NAK 分組。

  在上述協議中,當發送方處於等待ACK或NAK狀態時,它不能從上層得到更多數據。這樣子的協議被稱爲停等協議 (stop-and-wait)資源

  • rdt 2.0 的接收端仍然只有一個狀態。狀態變遷取決於收到的分組是否受損,有兩種方式:
    • 若是收到的分組受損,即 rdt_rcv(rcvpkt) && corrupt(rcvpkt),則返回 NAK 分組
    • 若是收到的分組無缺,即 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt),則返回 ACK 分組
  • 處理完後仍然返回自身這個狀態,繼續等待下一次從底層接收分組並處理。

 

【rdt2.1 解決 ACK/NAK 分組受損的引入序號的協議

  rdt2.1 彷佛是一個能夠在有比特差錯信道上正常工做的可靠數據傳輸協議了,但仔細想一想,咱們沒有考慮 ACK 或 NAK 分組受損的狀況。

  處理ACK/NAK分組損壞的方法有如下三種:

  • 增長控制信令: 即發送方請求接收方重複ACK或NAK分組。但新的控制信令也可能受損。
  • 增長足夠的校驗和比特: 使發送方不只能夠檢測差錯,還能夠恢復差錯。對於會產生差錯卻不會丟失分組的信道,能夠直接解決問題。
  • 重傳當前數據分組: 發送方收到損壞的ACK或NAK分組時,重傳當前數據分組。這種方法在信道中引入了冗餘分組 (duplicate packet)。 這致使接收方不知道接收到的分組是新數據分組的仍是一次數據重傳。

  想要解決這個問題,咱們須要在數據分組中添加一個新的字段,而後讓發送端對其數據分組編號,將發送數據分組的序號放在該字段中。因而,接收端只須要檢查序號就能夠肯定收到的分組是不是一次從新傳送的分組。

  咱們把引入序號的協議稱爲rdt 2.1,FSM圖以下。

 

  • 按照上圖來描述一下 rdt 2.1 協議發送端的狀態變遷過程:
    • 首先由較高層觸發 rdt_send(data) 事件,經過 sndpkt = make_pkt(0, data, checksum) 產生一個序號爲 0,包含待發送數據且帶有校驗和的分組,接着經過 udt_send(sndpkt) 將其發送到信道中,而後狀態變遷爲「等待接收接收端的 ACK 或 NAK 0」
    • 當發送端收到了一個來自接收端的分組數據:
      • 若是該分組數據受損,或者接收到的是 NAK 分組,那麼經過 udt_send(sndpkt) 從新傳送剛纔的序號爲 0 的分組到信道中
      • 若是該分組無缺且收到的是 ACK 分組,那麼發送端知道接收端已經成功接收了剛纔發送的序號爲 0 的分組,此時發送端狀態變遷到等待較高層傳下來的數據發送請求
    • 接着再次由較高層觸發 rdt_send(data) 事件,經過 sndpkt = make_pkt(1, data, checksum) 產生一個序號爲 1,包含待發送數據且帶有校驗和的分組,接着經過 udt_send(sndpkt) 將其發送到信道中,而後狀態變遷爲「等待接收接收端的 ACK 或 NAK 1」
    • 當發送端再次收到了一個來自接收端的分組數據:
      • 若是該分組數據受損,或者接收到的是 NAK 分組,那麼經過 udt_send(sndpkt) 從新傳送剛纔的序號爲 1 的分組到信道中
      • 若是該分組無缺且收到的是 ACK 分組,那麼發送端知道接收端已經成功接收了剛纔發送的序號爲 1 的分組,此時發送端狀態變遷到等待較高層傳下來的數據發送請求(即回到本狀態機的初始狀態)
  • 接着再來描述一下 rdt 2.1 協議接收端的狀態變遷過程:
    • 首先在初始狀態上,接收端等待着接收由發送端發來的序號爲 0 的分組數據
    • 接着由 rdt_rcv(rcvpkt) 從底層信道接收了一個分組數據:
      • 若是該分組受損(即 rdt_crv(rcvpkt) && corrupt(rcvpkt)),那麼由 sndpkt = make_pkt(NAK, checksum) 產生一個附帶校驗和的 NAK 分組,接着由 udt_send(sndpkt) 發送回發送端
      • 若是該分組失序(即 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt)),那麼由 sndpkt = make_pkt(ACK, checksum) 產生一個附帶校驗和的 ACK 分組,接着由 udt_send(sndpkt)發送回發送端
      • 若是該分組無缺且順序正確(即 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq0(rcvpkt)),那麼經過 extract(rcvpkt, data) 和 deliver_data(data) 將分組數據上傳給較高層程序。接着,由 sndpkt = make_pkt(ACK, checksum) 產生一個附帶校驗和的 ACK 分組,由 udt_send(sndpkt) 發送回發送端
    • 接下來等待序號爲 1 的分組的處理過程與上面相似,再也不贅述

 

【rdt2.2 只用ACK的協議】

  協議rdt 2.1 使用了確定確認和否認確認。當接收到正確的分組時,接收方發送一個「確定確認」,當接收到受損的分組時,發送一個「否認確認」。若是不發送NAK,而是對上次正確接收的分組發送一個ACK,也能夠實現同樣的效果。發送方若是接收到兩個同樣的ACK,就說明接收方沒有正確接收到跟在被確認兩次的分組後面的分組。
  咱們把只使用ACK的協議稱爲rdt 2.2,其FSM圖以下。

  具體 rdt 2.2 的流程由於和 rdt 2.1 基本相似,故不贅述。

 

## 經具備比特差錯的丟包信道的可靠數據傳輸:rdt 3.0

  在現實的網絡環境中,除了比特受損外,底層信道還會丟包;有不少可能的方法能夠解決丟包問題,這裏咱們讓發送方負責檢測和恢復丟包工做。

  假定發送端傳輸一個數據分組,該分組發生丟失 或者 接收端對該分組的 ACK 發生了丟失。在這兩種狀況下,發送端都收不到應當到來的接收端的響應。因此,若是發送端願意等待足夠長的時間以肯定該分組缺失已丟失,則它只須要重傳該數據分組便可。

  從發送端的觀點來看,重傳是一個萬能靈藥。爲了實現基於時間的重傳機制,須要一個倒數計時器 (countdown timer),在一個給定的時間量過時以後,可中斷髮送方。發送方須要作到:1)每次發送一個分組(包括第一次分組和重傳分組)時,就啓動一個定時器;2)相應定時器中斷;3)終止定時器。

  下圖是rdt 3.0的發送方FSM,該協議運行在可能發生出錯和丟失的信道上。

rdt 2.2 協議中的接收端有限狀態機描述圖仍然適用於 rdt 3.0 協議,下面我仍然用文字來簡要描述一下上圖中的發送端發送分組流程:

  • 首先由較高層觸發 rdt_send(data) 事件,經過 sndpkt = make_pkt(0, data, checksum) 產生一個序號爲 0,包含待發送數據且帶有校驗和的分組,接着經過 udt_send(sndpkt) 將其發送到信道中並啓動定時器,而後狀態變遷爲「等待接收接收端的 ACK 0」
  • 當發送端在「等待接收接收端的 ACK 0」的時候:
    • 若是收到了受損的分組(即 corrupt(rcvpkt))或者收到了 ACK 1(即 isACK(rcvpkt, 1),也就是收到了本身發送的上一個分組的 ACK),則直接忽略
    • 若是定時器時間到,則由 udt_send(sndpkt) 從新發送該分組並從新啓動定時器
    • 若是收到了無缺的分組且 ACK 爲 0,那麼發送端知道接收端已經成功接收了剛纔發送的序號爲 0 的分組,直接中止定時器,此時發送端狀態變遷到等待較高層傳下來的數據發送請求
  • 注意在繼續等待從較高層傳下來的數據發送請求的過程當中,若是收到了任何分組數據包,都直接忽略,由於它們必定是冗餘的
  • 接下來繼續重複上面的流程,只是改變了序號,再也不贅述

 

## rdt 3.0 的性能分析

  假設有兩臺主機,分別位於美國西海岸和東海岸,端對端延時 大約爲 30ms,假定它們經過一條速率 R 爲 1Gbps 的信道相連。包括首部字段和數據的分組長 L 爲 1KB (8000 bits),因此發送一個分組進入 1Gbps 鏈路實際所需

  若是發送方在 t=0 時刻開始發送分組,則在 8μs 後,最後1bit進入了發送端信道。通過 15ms 後,分組的第一個 bit 到達接收端;在 15.008ms 時刻,分組的最後一個 bit 到達接收端。假設接收端的 ACK 產生和發送不佔用時間,則再通過 15ms 之後,即t=30.008ms,發送端接收到接收端的ACK,發送端能夠發送下一個分組。

  在 30.008ms 內,發送方的發送使用了0.008ms。咱們定義信道利用率爲:發送方實際忙於發送比特到信道的時間與發送時間之比,則中止等待協議的發送方利用率爲:

  在1G連路上每30毫秒才發送一個分組(33KB/s),這就是網絡協議限制了物理資源的利用的例子。

 

##  可靠數據傳輸協議的技術

   校驗和序號定時器確定和否認確認分組,這些技術都在協議的運行中起到了必不可少的做用。如今 rdt 3.0 已是一個功能正確的協議,但由於它的本質仍然是停等協議,因此效率實在捉急。在本筆記的下篇中,將介紹流水線可靠數據傳輸協議、回退 N 步協議以及選擇重傳協議,最終將會獲得一個可靠而且效率較高的協議實現方法。

相關文章
相關標籤/搜索