最近在做UDP相關(guān)的工作,今天給大家分享一篇關(guān)于網(wǎng)絡(luò)方面的優(yōu)秀文章!
一、udp與tcp的區(qū)別:
TCP(TransmissionControl Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
UDP是User Datagram Protocol,一種無連接的傳輸層協(xié)議,提供面向事務(wù)的簡單不可靠信息傳送服務(wù)??煽啃杂缮蠈討?yīng)用實現(xiàn),所以要實現(xiàn)udp可靠性傳輸,必須通過應(yīng)用層來實現(xiàn)和控制。
二、TCP如何實現(xiàn)可靠性傳輸:
可靠性:
應(yīng)用數(shù)據(jù)被分割成TCP認為最適合發(fā)送的數(shù)據(jù)塊。這和UDP完全不同,應(yīng)用程序產(chǎn)生的數(shù)據(jù)長度將保持不變。由TCP傳遞給IP的信息單位稱為報文段或段(segment)。
當TCP發(fā)出一個段后,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發(fā)這個報文段。當TCP收到發(fā)自TCP連接另一端的數(shù)據(jù),它將發(fā)送一個確認。TCP有延遲確認的功能,在此功能沒有打開,則是立即確認。功能打開,則由定時器觸發(fā)確認時間點。
TCP將保持它首部和數(shù)據(jù)的檢驗和。這是一個端到端的檢驗和,目的是檢測數(shù)據(jù)在傳輸過程中的任何變化。如果收到段的檢驗和有差錯,TCP將丟棄這個報文段和不確認收到此報文段(希望發(fā)端超時并重發(fā))。
既然TCP報文段作為IP數(shù)據(jù)報來傳輸,而IP數(shù)據(jù)報的到達可能會失序,因此TCP報文段的到達也可能會失序。如果必要,TCP將對收到的數(shù)據(jù)進行重新排序,將收到的數(shù)據(jù)以正確的順序交給應(yīng)用層。
既然IP數(shù)據(jù)報會發(fā)生重復(fù),TCP的接收端必須丟棄重復(fù)的數(shù)據(jù)。
TCP還能提供流量控制。TCP連接的每一方都有固定大小的緩沖空間。TCP的接收端只允許另一端發(fā)送接收端緩沖區(qū)所能接納的數(shù)據(jù)。這將防止較快主機致使較慢主機的緩沖區(qū)溢出。
重傳策略:
TCP協(xié)議用于控制數(shù)據(jù)段是否需要重傳的依據(jù)是設(shè)立重發(fā)定時器。在發(fā)送一個數(shù)據(jù)段的同時啟動一個重傳,如果在重傳超時前收到確認(Acknowlegement)就關(guān)閉該重傳,如果重傳超時前沒有收到確認,則重傳該數(shù)據(jù)段。在選擇重發(fā)時間的過程中,TCP必須具有自適應(yīng)性。它需要根據(jù)互聯(lián)網(wǎng)當時的通信情況,給出合適的重發(fā)時間。
這種重傳策略的關(guān)鍵是對定時器初值的設(shè)定。采用較多的算法是Jacobson于1988年提出的一種不斷調(diào)整超時時間間隔的動態(tài)算法。其工作原理是:對每條連接TCP都保持一個變量RTT(Round Trip Time),用于存放當前到目的端往返所需要時間最接近的估計值。當發(fā)送一個數(shù)據(jù)段時,同時啟動連接的定時器,如果在定時器超時前確認到達,則記錄所需要的時間(M),并修正[2] RTT的值,如果定時器超時前沒有收到確認,則將RTT的值增加1倍。通過測量一系列的RTT(往返時間)值,TCP協(xié)議可以估算數(shù)據(jù)包重發(fā)前需要等待的時間。在估計該連接所需的當前延遲時通常利用一些統(tǒng)計學的原理和算法(如Karn算法),從而得到TCP重發(fā)之前需要等待的時間值。
窗口確認:
TCP的一項功能就是確保每個數(shù)據(jù)段都能到達目的地。位于目的主機的TCP服務(wù)對接受到的數(shù)據(jù)進行確認,并向源應(yīng)用程序發(fā)送確認信息。使用數(shù)據(jù)報頭序列號以及確認號來確認已收到包含在數(shù)據(jù)段的相關(guān)的數(shù)據(jù)字節(jié)。
TCP在發(fā)回源設(shè)備的數(shù)據(jù)段中使用確認號,指示接收設(shè)備期待接收的下一字節(jié)。這個過程稱為期待確認。
源主機在收到確認消息之前可以傳輸?shù)臄?shù)據(jù)的大小稱為窗口大小。用于管理丟失數(shù)據(jù)和流量控制。
三、udp如何實現(xiàn)可靠性傳輸:
UDP它不屬于連接型協(xié)議,因而具有資源消耗小,處理速度快的優(yōu)點,所以通常音頻、視頻和普通數(shù)據(jù)在傳送時使用UDP較多,因為它們即使偶爾丟失一兩個數(shù)據(jù)包,也不會對接收結(jié)果產(chǎn)生太大影響。
傳輸層無法保證數(shù)據(jù)的可靠傳輸,只能通過應(yīng)用層來實現(xiàn)了。實現(xiàn)的方式可以參照tcp可靠性傳輸?shù)姆绞?,只是實現(xiàn)不在傳輸層,實現(xiàn)轉(zhuǎn)移到了應(yīng)用層。
實現(xiàn)確認機制、重傳機制、窗口確認機制。
如果你不利用Linux協(xié)議棧以及上層socket機制,自己通過抓包和發(fā)包的方式去實現(xiàn)可靠性傳輸,那么必須實現(xiàn)如下功能:
發(fā)送:包的分片、包確認、包的重發(fā)
接收:包的調(diào)序、包的序號確認
目前有如下開源程序利用udp實現(xiàn)了可靠的數(shù)據(jù)傳輸。分別為RUDP、RTP、UDT。
RUDP:
RUDP 提供一組數(shù)據(jù)服務(wù)質(zhì)量增強機制,如擁塞控制的改進、重發(fā)機制及淡化服務(wù)器算法等,從而在包丟失和網(wǎng)絡(luò)擁塞的情況下, RTP 客戶機(實時位置)面前呈現(xiàn)的就是一個高質(zhì)量的 RTP 流。在不干擾協(xié)議的實時特性的同時,可靠 UDP 的擁塞控制機制允許 TCP 方式下的流控制行為。
RTP:
實時傳輸協(xié)議(RTP)為數(shù)據(jù)提供了具有實時特征的端對端傳送服務(wù),如在組播或單播網(wǎng)絡(luò)服務(wù)下的交互式視頻音頻或模擬數(shù)據(jù)。應(yīng)用程序通常在 UDP 上運行 RTP 以便使用其多路結(jié)點和校驗服務(wù);這兩種協(xié)議都提供了傳輸層協(xié)議的功能。但是 RTP 可以與其它適合的底層網(wǎng)絡(luò)或傳輸協(xié)議一起使用。如果底層網(wǎng)絡(luò)提供組播方式,那么 RTP 可以使用該組播表傳輸數(shù)據(jù)到多個目的地。
RTP 本身并沒有提供按時發(fā)送機制或其它服務(wù)質(zhì)量(QoS)保證,它依賴于底層服務(wù)去實現(xiàn)這一過程。RTP 并不保證傳送或防止無序傳送,也不確定底層網(wǎng)絡(luò)的可靠性。RTP 實行有序傳送, RTP 中的序列號允許接收方重組發(fā)送方的包序列,同時序列號也能用于決定適當?shù)陌恢?,例如:在視頻解碼中,就不需要順序解碼。
UDT:
基于UDP的數(shù)據(jù)傳輸協(xié)議(UDP-basedData Transfer Protocol,簡稱UDT)是一種互聯(lián)網(wǎng)數(shù)據(jù)傳輸協(xié)議。UDT的主要目的是支持高速廣域網(wǎng)上的海量數(shù)據(jù)傳輸,而互聯(lián)網(wǎng)上的標準數(shù)據(jù)傳輸協(xié)議TCP在高帶寬長距離網(wǎng)絡(luò)上性能很差。顧名思義,UDT建于UDP之上,并引入新的擁塞控制和數(shù)據(jù)可靠性控制機制。UDT是面向連接的雙向的應(yīng)用層協(xié)議。它同時支持可靠的數(shù)據(jù)流傳輸和部分可靠的數(shù)據(jù)報傳輸。由于UDT完全在UDP上實現(xiàn),它也可以應(yīng)用在除了高速數(shù)據(jù)傳輸之外的其它應(yīng)用領(lǐng)域,例如點到點技術(shù)(P2P),防火墻穿透,多媒體數(shù)據(jù)傳輸?shù)鹊取?/p>
因項目中的需要,現(xiàn)在詳細分析一下UDT是如何通過udp實現(xiàn)數(shù)據(jù)的可靠傳輸。通過閱讀源碼的方式。
四、UDT原理分析:
主要通過分析源碼來弄清楚如何利用udp實現(xiàn)數(shù)據(jù)的可靠性傳輸,主要按照協(xié)議格式、關(guān)鍵數(shù)據(jù)結(jié)構(gòu)等展開。
UDT應(yīng)用層協(xié)議:
UDT并不是在瓶勁帶寬相對較小的和大量多元短文檔流的情況下用來取代TCP的。
UDT主要作為TCP的朋友,和TCP并存,UDT分配的帶寬不應(yīng)該超過根據(jù)MAX-MIN規(guī)則的最大最小公平共享原則。(備注,最大最小規(guī)則允許UDT在高BDP連接下分配TCP不能使用的可用帶寬)。
UDT是雙工的,每個UDT實體有兩個部分:發(fā)送和接收。
發(fā)送者根據(jù)流量控制和速率控制來發(fā)送(和重傳)應(yīng)用程式數(shù)據(jù)。
接收者接收數(shù)據(jù)包和控制包,并根據(jù)接收到的包發(fā)送控制包。發(fā)送和接收程式共享同一個UDP端口來發(fā)送和接收。
接收者也負責觸發(fā)和處理任何的控制事件,包括擁塞控制和可靠性控制和他們的相對機制,例如RTT估計、帶寬估計、應(yīng)答和重傳。
UDT總是試著將應(yīng)用層數(shù)據(jù)打包成固定的大小,除非數(shù)據(jù)不夠這么大。和TCP相似的是,這個固定的包大小叫做MSS(最大包大?。?。由于期望UDT用來傳輸大塊數(shù)據(jù)流,我們假定只有很小的一部分不規(guī)則的大小的包在UDT session中。MSS能夠通過應(yīng)用程式來安裝,MTU是其最優(yōu)值(包括任何包頭)。
UDT擁塞控制算法將速率控制和窗口(流量控制)合并起來,前者調(diào)整包的發(fā)送周期,后者限制最大的位被應(yīng)答的包。在速率控制中使用的參數(shù)通過帶寬估計技術(shù)來更新,他繼承來自基于接收的包方法。同時,速率控制周期是估計RTT的常量,流控制參數(shù)依賴于對方的數(shù)據(jù)到達速度,另外接收端釋放的緩沖區(qū)的大小。
報文類型及格式:
UDT有兩種包:數(shù)據(jù)包和控制包。他們通過包頭的第一位來區(qū)分(標志位)。如果是0,表示是數(shù)據(jù)包,1表示是控制包。
數(shù)據(jù)包:
數(shù)據(jù)包結(jié)構(gòu)如下顯示:
包序號是UDT數(shù)據(jù)包頭中唯一的內(nèi)容。它是一個無符號整數(shù),使用標志位后的31位,UDT使用包基礎(chǔ)的需要,例如,每個非重傳的包都增加序號1。序號在到達最大值2^31-1的時候覆蓋。緊跟在這些數(shù)據(jù)后面的是應(yīng)用程序數(shù)據(jù)。
控制包:
控制包結(jié)構(gòu)如下:
有6種類型的控制包在UDT中,bit1-3表示這些信息。前32位在包頭中必須存在??刂菩畔⒆侄伟?(例如,它不存在)或者多個32位無符號整數(shù),這由包類型決定。
UDT使用應(yīng)答子序號的方法。每個ACK/ACK2包有一個無符號的16位序號,它獨立于數(shù)據(jù)包需要。它使用位16-31。應(yīng)答需要從0到(2^16-1)。位16-31在其他控制包中沒有定義。
注意,對于數(shù)據(jù)和控制包來說,可以從UDP協(xié)議頭中得到實際的包大小。包大小信息能被用來得到有效的數(shù)據(jù)負載和NAK包中的控制信息字段大小。
定時器:
UDT在接收端使用4個定時器來觸發(fā)不同的周期事件,包括速率控制、應(yīng)答、丟失報告(negative應(yīng)答)和重傳/連接維護。
UDT中的定時器使用系統(tǒng)時間作為源。UDT接收端主動查詢系統(tǒng)時間來檢查一個定時器是否過期。對于某個定時器T來說,其擁有周期TP,將定變量t用來記錄最近T被設(shè)置或復(fù)位的時間。如果T在系統(tǒng)時間t0(t= t0)被復(fù)位,那么任何t1(t1-t>=TP)是T過期的條件。
四個定時器是:RC定時器、ACK定時器、NAK定時器、EXP定時器。他們的周期分別是:RCTP、ATP、NTP、ETP。
RC定時器用來觸發(fā)周期性的速率控制。ACK定時器用來觸發(fā)周期性的有選擇的應(yīng)答(應(yīng)答包)。RCTP和ATP是常量值,值為:RCTP=ATP=0.01秒。
NAK被用來觸發(fā)negative應(yīng)答(NAK包)。重傳定時器被用來觸發(fā)一個數(shù)據(jù)包的重傳和維護連接狀態(tài)。他們周期依賴于對于RTT的估計。ETP值也依賴于連續(xù)EXP時間溢出的次數(shù)。推薦的RTT初始值是0.1秒,而NTP和ETP的初始值是:NTP=3RTT,ETP=3RTT+ATP。
在每次bounded UDP接收操作(如果收到一個UDP包,一些額外的必須的數(shù)據(jù)處理時間)時查詢系統(tǒng)時間來檢查四個定時器是否已經(jīng)過期。推薦的周期粒度是微秒。UDP接收時間溢出值是實現(xiàn)的一個選擇,這依賴于循環(huán)查詢的負擔和事件周期精確度之間的權(quán)衡。
速率控制事件更新包發(fā)送周期,UDT發(fā)送端使用STP來安排數(shù)據(jù)包的發(fā)送。假定一個在時間t0被發(fā)送,那么下一次包發(fā)送時間是(t0+ STP)。換句話說,如果前面的包發(fā)送花費了t’時間,發(fā)送端將等待(STP-t’)來發(fā)送下一個數(shù)據(jù)包(如果STP-t’ <0,就不需要等待了)。這個等待間隔需要一個高精確度的實現(xiàn),推薦使用CPU時鐘周期粒度。
最簡單的方式是在應(yīng)用層模仿傳輸層TCP的可靠性傳輸。下面不考慮擁塞處理,談?wù)勛约旱膫€人簡單粗暴的設(shè)計:
1、添加seq/ack機制,確保數(shù)據(jù)發(fā)送到對端。
2、添加發(fā)送和接收緩沖區(qū),主要是用戶超時重傳。
3、添加超時重傳機制。
發(fā)送端發(fā)送數(shù)據(jù)時,生成一個隨機seq=x,然后每一片按照數(shù)據(jù)大小分配seq。數(shù)據(jù)到達接收端后接收端放入緩存,并發(fā)送一個ack=x的包,表示對方已經(jīng)收到了數(shù)據(jù)。發(fā)送端收到了ack包后,刪除緩沖區(qū)對應(yīng)的數(shù)據(jù)。
時間到后,定時任務(wù)檢查是否需要重傳數(shù)據(jù)。
如下是tcp的確認機制
開源項目:
https://github.com/caozhiyi/Hudp
編輯:黃飛
?
評論
查看更多