禁止碼迷,布布扣,豌豆代理,碼農教程,愛碼網等第三方爬蟲網站爬取!
可靠數據傳輸原理
可靠數據傳輸的關鍵在於數據不錯、不丟、不亂,可靠數據傳輸為上層實體提供的服務,可以抽象為數據通過一條可靠的信道進行傳輸。在可靠信道的保護下,傳輸的數據比特流不會被損壞或丟失,而且所有分組都會按需交付。
但是實際上並沒有所謂的可靠信道,網絡層的 IP 協議是不可靠信道,不可靠的信道實現可靠的傳輸需要雙向控制信息流動。因此就需要一種可靠數據傳輸協議(rdt)在不可靠信道上提供可靠信道傳輸,信道的不可靠性決定了可靠數據傳輸協議的復雜性。因此對可靠數據傳輸協議的考慮,需要從簡單到復雜的情景進行強化。
經完全可靠信道
首先考慮最簡單的情況,此時的下層信道是可靠信道,也就是說信道滿足不發生錯誤、不丟棄分組的條件。因此對於可靠信道,數據的發送端和接收端僅需要完成數據的發送、接收工作。
發送端
由於信道完全可靠,因此發送端僅需要完成數據發送的工作。其對應的 FSM 僅有一個狀態,完成一次數據發送工作之后,狀態就返回其自身。
接收端
由於信道完全可靠,因此接收端僅需要完成數據接收的工作。其對應的 FSM 僅有一個狀態,完成一次數據接收工作之后,狀態就返回其自身。
由此可見當信道是完全可靠時,發送端和接收端不需要任何反饋機制,也不需要任何查錯機制。
經具有比特差錯信道
自動重傳請求協議
現在考慮信道並不可靠,而是會發生比特差錯的情況,也就是經過信道的數據可能會發生位錯誤。此時為了反饋比特差錯的發生,協議需要引入反饋機制,也就是使用肯定確認和否定確認報文來反饋傳輸的情況,若收到了否定確認就需要重傳數據報。引入反饋機制和重傳機制的協議稱之為自動重傳請求協議。
具體這個協議需要什么機制來實現?需要以下 3 種功能:
- 差錯檢測:在數據分組中加入校驗和,通過校驗和進行查錯;
- 接收方反饋:接收方接收數據時,需要向發送方發送反饋信息,即為發送 ACK 或 NAK。一般來說只需要 1 個比特長來表示,0 表示 NAK,1 表示 ACK;
- 重傳:當數據出錯時,發送方需要支持數據重傳。
發送端
在引入反饋機制和重傳機制后,發送端就需要 2 個狀態來進行工作。首先第一個狀態用於等待上層的調用,並進行數據發生的工作,發送數據時需要封裝校驗和。當數據發送成功后,就需要切換到下一個狀態,此時協議需要等待接收端的反饋信息。若收到的信息是 NAK,則發送端需要重傳數據,但是此時狀態不發生改變。只有接收端發來 ACK 表示數據成功接收后,就可以回復到第一個狀態。
我們可以觀察到當發送方等待反饋信息時,不能夠進行發送數據的任務,僅有等待到 ACK 之后才能切換狀態。因此這種行為,協議也可以被稱之為停止-等待協議。
接收端
對於接收端而言只需要 1 種狀態,但是該狀態需要針對數據的正確性,而做出不同的應答。當通過校驗和發現數據出錯時,發送 NAK 要求發送方重傳,當經過校驗確認信息無誤時,發送 ACK 表示數據成功接收。
現在的自動重傳請求協議,可以實現可靠數據傳輸嗎?
考慮應答報文出錯
上文的自動重傳請求協議存在一個關鍵的漏洞,既然數據分組會出錯,那么 ACK 或 NAK 分組也同樣會有出錯的可能。此時有 3 種方案可以考慮:
- 增加校驗和,對應答報文也使用校驗和進行校驗,但是發送端會困惑於這是對數據接收的反饋,還是對確認反饋的反饋;
- 增加額外控制信息,通過更多的信息令發送方不僅可以查錯,也可以進行錯誤修復,但是額外的信息也有可能出錯;
- 對於不正確的應答報文,直接重傳,但是這么做會給接收方引入冗余分組,接收方無法確認冗余分組的順序。
綜上所述,這些方法都有不足之處,如何使上述方法具有可行性?現實中廣泛應用的做法是添加序號字段,通過序號接收方就可以確認收到的分組是否是重傳過的,這樣發送發對於含糊的應答報文就可以放心地重傳。序號僅需要區分前一個分組和現分組,因此有 0 和 1 兩種序號,用於標記現在想收到的分組序號是 0 還是 1。這樣當發生了因應答報文出錯而引發的重傳,接收方就可以通過序號來判定是否是冗余分組,進行主動丟包了。
發送方
由於引入了 2 種序號,發送方的狀態將隨之翻兩倍,用於分別處理 0 和 1 兩種序號的數據。此時與上文不同在於,發送方需要為每個分組加上序號,然后對 ACK/NAK 報文進行校驗,發送方需要記住當前發送的分組序號以備重傳。
接收方
由於引入了 2 種序號,接收方的狀態將隨之翻兩倍,用於分別處理 0 和 1 兩種序號的數據。接收方雖然不能知道反饋信息是否被成功接收,但是可以通過判斷分組是否重復(當前所處狀態的分組序號是否是期望分組序號)來配合發送方的重傳。
僅使用 ACK
引入了序號之后,我們能不能實現不依靠 NAK,僅使用 ACK 來完成可靠傳輸呢?這種想法是可行的,此時當收到錯誤的分組時,接收方不發送 NAK,而是發送 ACK + 上一個正確分組的序號。當發送方收到同一個分組的 2 個 ACK 時也可以判斷出接收方沒有收到被確認 2 次的分組后的所有分組,此時就需要進行重傳。
經具有比特差錯的丟包信道
比特交替協議
上文我們解決了數據發生比特錯誤的問題,但是在實際情況下有可能分組並不是發生錯誤,而是直接在某個地方被丟棄了。根據停止等待協議,當發送端在等待 ACK 時,並不能處理后續的數據,而如果分組發送時發生了丟包,接收端將永遠等待數據的傳輸,不會發送 ACK;若接收端發送了 ACK,但是 ACK 發生了丟包,則發送端也會永遠等待下去。也就是說,如果沒有發現丟包,有可能協議就不進行工作了。
此時對於協議而言,就需要考慮如何發現丟包的情況,以及丟包之后要怎么做。我們可以讓發送端來負責對丟包的檢測,當上述情況發生時,發送方都不會受到 ACK。所以若發送方等待足夠長的時間沒有收到 ACK,那么在邏輯上就可以認為發生了丟包,此時僅需要重傳分組即可。為了基於時間來判斷是否重傳,發送方需要一個倒計數計時器,發送方需要做到每發送一次分組就啟動一次計時器,等待一段時間沒收到 ACK 就重傳並重啟計時器,收到 ACK 后終止計時器。
現在再考慮一個問題,若接收方收到了分組,而 ACK 也沒有丟包,但是經歷了超過計時器限定的時間的較大時延才被發送端接收的情況。這個問題在上述的自動重傳請求協議已經解決,即使發送端重傳了數據,接收端也可以使用序號來對於冗余的數據分組。由於分組序號在 0 和 1 之間交替,該協議也被稱為比特交替協議。
流程分析
傳輸過程無丟包
分組丟包
ACK 丟包
ACK 超時接收
到此為止,我們得到了一個可靠數據傳輸協議!
參考資料
《計算機網絡 自頂向下方法》 [美] James F.Kurose,Keith W.Ross 著,陳鳴 譯,機械工業出版社