UDP 如何實現可靠性傳輸?
UDP 不屬於連接性協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳輸時使用 UDP 較多,因為它們即使偶爾丟失一兩個包,也不會對接收結果產生太大影響
傳輸層無法保證數據的可靠傳輸,只能通過應用層來實現,實現的方式可以參考 TCP 可靠性傳輸,只是實現不在傳輸層,實現轉移到了應用層
實現確認機制,重傳機制,窗口確認機制
如果不利用 Linux 協議棧及上層 socket 機制,自己通過抓包和發包的方式去實現可靠性傳輸,那么必須實現以下功能
發送:包的分片、包確認、包的重發
接收:包的調序、包的序號確認
目前已有如下開源程序利用 UDP 實現了可靠的數據傳輸,分別為:RUDP、RTP、UDT
RUDP
RUDP 提供一組數據服務質量增強機制,如擁塞控制的改進、重發機制及淡化服務器算法等,從而在包丟失和網絡擁塞的情況下, RTP 客戶機(實時位置)面前呈現的就是一個高質量的 RTP 流。在不干擾協議的實時特性的同時,可靠 UDP 的擁塞控制機制允許 TCP 方式下的流控制行為
RTP
實時傳輸協議(RTP)為數據提供了具有實時特征的端對端傳送服務,如在組播或單播網絡服務下的交互式視頻音頻或模擬數據。應用程序通常在 UDP 上運行 RTP 以便使用其多路結點和校驗服務;這兩種協議都提供了傳輸層協議的功能。但是 RTP 可以與其它適合的底層網絡或傳輸協議一起使用。如果底層網絡提供組播方式,那么 RTP 可以使用該組播表傳輸數據到多個目的地。
RTP 本身並沒有提供按時發送機制或其它服務質量(QoS)保證,它依賴於底層服務去實現這一過程。 RTP 並不保證傳送或防止無序傳送,也不確定底層網絡的可靠性。 RTP 實行有序傳送, RTP 中的序列號允許接收方重組發送方的包序列,同時序列號也能用於決定適當的包位置,例如:在視頻解碼中,就不需要順序解碼。
UDT
基於 UDP 的數據傳輸協議(UDP-basedData Transfer Protocol,簡稱UDT)是一種互聯網數據傳輸協議。UDT的主要目的是支持高速廣域網上的海量數據傳輸,而互聯網上的標准數據傳輸協議 TCP 在高帶寬長距離網絡上性能很差。顧名思義,UDT 建於 UDP 之上,並引入新的擁塞控制和數據可靠性控制機制。UDT 是面向連接的雙向的應用層協議。它同時支持可靠的數據流傳輸和部分可靠的數據報傳輸。由於 UDT 完全在 UDP 上實現,它也可以應用在除了高速數據傳輸之外的其它應用領域,例如點到點技術(P2P),防火牆穿透,多媒體數據傳輸等等。
因項目中的需要,現在詳細分析一下 UDT 是如何通過 udp 實現數據的可靠傳輸。通過閱讀源碼的方式。
UDT 原理分析
主要通過分析源碼弄清如何使用 UDP 進行數據的可靠傳輸,主要按照協議格式,關鍵數據等展開
UDT 應用層協議
UDT 並不是在瓶勁帶寬相對較小的和大量多元短文檔流的情況下用來取代 TCP 的。
UDT 主要作為 TCP 的朋友,和 TCP 並存,UDT 分配的帶寬不應該超過根據 MAX-MIN 規則的最大最小公平共享原則。(備注,最大最小規則允許 UDT 在高 BDP 連接下分配 TCP 不能使用的可用帶寬)。
UDT 是雙工的,每個 UDT 實體有兩個部分:發送和接收。
發送者根據流量控制和速率控制來發送(和重傳)應用程式數據。
接收者接收數據包和控制包,並根據接收到的包發送控制包。發送和接收程式共享同一個UDP端口來發送和接收。
接收者也負責觸發和處理任何的控制事件,包括擁塞控制和可靠性控制和他們的相對機制,例如RTT估計、帶寬估計、應答和重傳。
UDT總是試着將應用層數據打包成固定的大小,除非數據不夠這么大。和TCP相似的是,這個固定的包大小叫做MSS(最大包大小)。由於期望UDT用來傳輸大塊數據流,我們假定只有很小的一部分不規則的大小的包在UDT session中。MSS能夠通過應用程式來安裝,MTU是其最優值(包括任何包頭)。
UDT擁塞控制算法將速率控制和窗口(流量控制)合並起來,前者調整包的發送周期,后者限制最大的位被應答的包。在速率控制中使用的參數通過帶寬估計技術來更新,他繼承來自基於接收的包方法。同時,速率控制周期是估計RTT的常量,流控制參數依賴於對方的數據到達速度,另外接收端釋放的緩沖區的大小。
報文類型及格式
UDT有兩種包:數據包和控制包。他們通過包頭的第一位來區分(標志位)。如果是0,表示是數據包,1表示是控制包。
數據包
控制包
定時器
UDT在接收端使用4個定時器來觸發不同的周期事件,包括速率控制、應答、丟失報告(negative應答)和重傳/連接維護。
UDT中的定時器使用系統時間作為源。UDT接收端主動查詢系統時間來檢查一個定時器是否過期。對於某個定時器T來說,其擁有周期TP,將定變量t用來記錄最近T被設置或復位的時間。如果T在系統時間t0(t= t0)被復位,那么任何t1(t1-t>=TP)是T過期的條件。
四個定時器是:RC定時器、ACK定時器、NAK定時器、EXP定時器。他們的周期分別是:RCTP、ATP、NTP、ETP。
RC定時器用來觸發周期性的速率控制。ACK定時器用來觸發周期性的有選擇的應答(應答包)。RCTP和ATP是常量值,值為:RCTP=ATP=0.01秒。
NAK被用來觸發negative應答(NAK包)。重傳定時器被用來觸發一個數據包的重傳和維護連接狀態。他們周期依賴於對於RTT的估計。ETP值也依賴於連續EXP時間溢出的次數。推薦的RTT初始值是0.1秒,而NTP和ETP的初始值是:NTP=3RTT,ETP=3RTT+ATP。
在每次bounded UDP接收操作(如果收到一個UDP包,一些額外的必須的數據處理時間)時查詢系統時間來檢查四個定時器是否已經過期。推薦的周期粒度是微秒。UDP接收時間溢出值是實現的一個選擇,這依賴於循環查詢的負擔和事件周期精確度之間的權衡。
速率控制事件更新包發送周期,UDT發送端使用STP來安排數據包的發送。假定一個在時間t0被發送,那么下一次包發送時間是(t0+ STP)。換句話說,如果前面的包發送花費了t’時間,發送端將等待(STP-t’)來發送下一個數據包(如果STP-t’ <0,就不需要等待了)。這個等待間隔需要一個高精確度的實現,推薦使用CPU時鍾周期粒度。
個人感悟
最簡單的方式是在應用層模仿傳輸層TCP的可靠性傳輸。下面不考慮擁塞處理,談談自己的個人簡單粗暴的設計。
添加seq/ack機制,確保數據發送到對端。
添加發送和接收緩沖區,主要是用戶超時重傳。
添加超時重傳機制。
1、發送端發送數據時,生成一個隨機seq=x,然后每一片按照數據大小分配seq。數據到達接收端后接收端放入緩存,並發送一個ack=x的包,表示對方已經收到了數據。發送端收到了ack包后,刪除緩沖區對應的數據。
2、時間到后,定時任務檢查是否需要重傳數據。
————————————————
版權聲明:本文為CSDN博主「可可呦」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_41880190/article/details/89404864