UDP可靠傳輸那些事

2021-08-03 11:42:04 字數 4314 閱讀 5677

有空來論壇走走,發現討論udp可靠傳輸又熱了起來,有人認為udp高效率,有人認為udp丟包重傳機制容易控制,還有朋友搞極限測試,當然也有人推銷自己的東西,這裡寫一點我個人的看法。

udp可靠傳輸其實非常非常的簡單,我最開始接觸udp可靠傳輸大約是在2023年,因為那時候開發ftpanywhere,由於路由的對映和閘道器nat處理方面,認為udp具有天生優勢,因此開始編寫自己的udp可靠傳輸協議,好象那個時候已經有了udt,我也下了源**看了下,不過很快就看不下去了,因為它用了定時器,加上跨平台處理,導致它的**,反正我看著很亂,理不出乙個完整的邏輯圖。但是原理和tcp的基本一樣,並沒有什麼特殊的。後來我寫了我自己的第乙個udp可靠傳輸類,qtudp,這個是最簡單的,也就是和tcp一樣,實現2點之間的傳輸,並不是我現在寫的多點之間無中心p2p傳輸,效率很高,但是當時的編碼我還沒有養成現在的習慣,用了大量的dword之類的資料定義,包括包的定義,從現在角度看,不及格,不過至少它可以實用,並整合到了ftpanywhere軟體中,在除錯和執行過程中,慢慢的統計和發現udp包的傳輸中,最影響效能的部分以及其他一些細節,後來的ut 1.x多點傳輸協議就是在qtudp基礎上開發的,在到現在 ut 2.x , phoenix 2.x,實現了幾個跨越。

請相信,可靠udp傳輸從來都不是高效率可靠傳輸的代名詞,影響傳輸效率的最重要因素在於,sendto函式,每次只能投遞乙個mtu長度的包,頻繁的系統呼叫極大的影響了極限效能,也許你會說,udp預設可以達到64kb,你可以投遞大包,是的,可以投遞,但是由於網路上mtu裝置的限制,大包會被拆成小包,如果你定義乙個包大於mtu,那麼當其中任何乙個小包發生丟包的時候,會導致整個包需要重傳,這個開銷非常巨大,特別是在internet上,而採用mtu大小限制內的包進行傳輸,丟失乙個,只需要重傳乙個,開銷小的多。udp可靠傳輸的自定義校驗是另外乙個限制,為了避免偽造的udp包,我們需要在我們自己的可靠udp包中加入自定義的校驗,這個校驗方法也直接影響到效能,最快的是直接套用crc32校驗,由於目前cpu指令集對這個計算進行了優化,因此它的計算速度幾乎是最快的,但是代價是,人家要破解或者偽造你的udp包也很容易,因為演算法是透明的,以前暴出tcp偽造漏洞也是這樣,由於它的包組成是透明公開,唯一有保密性的是序列號,結果有些系統初始序列號存在規律,結果就導致了安全問題。最後,傳送和接收,由於是在應用層進行[無論你是採用api epoll select overlap io,最終的執行都是在應用層],這個傳送-確認過程中,由於應用層不是象tcp/ip協議棧那樣在核心態執行,因此可能有延遲,不過,目前的cpu核心數量和頻率,這個影響在工業應用[internet 等]已經幾乎可以忽略,唯一產生影響是在進行本機極限效能測試中。tcp的效率要高過udp可靠傳輸,因為它的send函式,幾乎每次都可以拷貝幾十kb,當然你可以將緩衝調整的很大,例如幾百kb或者幾mb,但是預設情況下的幾十kb足夠了,想當於幾十次呼叫udp sendto , 而tcp只需要呼叫一次,其次,tcp的包處理是在核心態進行,確認也是核心態,這就足以與應用層的udp可靠傳輸拉開距離,更別說硬體層的優化了. 那麼,你可能會認為,為什麼書上說udp效能好呢?其實這是針對不可靠udp傳輸,並且是內網 大包,例如

char buffs[32*1024];

memset(buffs,0,32*1024);

sendto(s , buffs,32*1024,.... 發射後不管,無論是否丟包

象這樣發包,效率才會超過tcp,不過,主要就是包頭大小的差距.

關於udp的穿透能力,也就是傳說中的打洞,這根本是個偽命題,有人還在那裡搞什麼測試說打通了4種 nat 模型, 你認為可能嗎? 還有人用猜埠的方法進行打洞,我了個去,工業上能這麼用? udp的穿透其實完全取決於路由[閘道器]的配置,國產的家用或者soho針對p2p進行過調整,但是你用cisco 等專業的大型裝置進行打洞看看,為了保護使用者的安全,一般管理員都設定了高安全非透明,通常,就算是內部同一臺電腦,同乙個udp埠,傳送給不同的目標ip資料報,路由都會隨機重新分配乙個埠,打洞根本不可能成功的. 所以,如果你為了nat處理而使用udp,建議你還是放棄吧,直接使用tcp+upnp就行.

關於udp可靠傳輸的效能,有人說使用epoll , overlap io 等,效率高於使用select模型, 我可以根據我的這幾年開發的經歷和測試結果告訴你,在校驗模式,投遞模式以及資料處理邏輯相同的情況下,多核心cpu平台下,本機效率差距不超過1%,而如果使用在internet上,效率差距無限接近0,現在是cpu過剩的年代,linux  windows的排程下,如果沒有核心態運算,那麼就會從等待的執行緒中挑選乙個,你不要以為從核心態切換到使用者態是不需要開銷的,這個開銷同樣很大,頻繁的排程同樣影響效能,雖然不算在你的**中而算在系統開銷中. 當然,如果你需要在linux系統中同時執行apache等web服務,那效率差距會比較明顯,因為程序和執行緒太多,得不到第一時間的排程.

關於udp可靠傳輸下緩衝大小,說實話,我是第一次見識,最簡單的點對點 udp可靠傳輸,有人開了上百kb的緩衝,緩衝是個好東西,通常,緩衝越大,效率越高,因為一次投遞的包數量多,io效能就高,但是,這在internet上是不提倡的,這種實現我不知道是否經過嚴格的網路丟包和負載測試,在有家用路由小頻寬上傳模式下,如果有多人或者多個網路程式使用頻寬,這個延遲引數變動非常頻繁,不必要的重傳率會非常高,最簡單的測試方法,找個銅包鋁網線,使用1 1對應的非標準接頭法,一頭接電腦,一頭接路由,然後與internet上遠端進行測試,估計這個丟包重傳的概率會高的嚇人.

udp可靠傳輸比tcp的慢啟動好?我想不一定,還是我上面那個網線做測試,如果採用快速啟動,在丟包嚴重的網路環境下,頻寬浪費太離譜了,我調整我自己的udp可靠傳輸啟動方法好多次,越來越覺得tcp的慢啟動是非常有道理的,雖然恢復的慢,但是,它因為錯誤重傳而產生頻寬的浪費是非常小的. 當然,如果考慮到效能,還是可以適當調整的快點.

關於udp可靠傳輸的檔案傳輸效率,這是個偽命題,這個極限是硬體本身造成的,首先,正常的udp可靠傳輸效率肯定高於普通硬碟的讀寫盤速度,即使用memory map 技術對檔案執行加速,還是跟不上udp本身的速度,其次,檔案傳輸協議會影響到傳輸效率,最快的模式是什麼? 就是直接傳送檔案從開始到結尾,和流 [ftp資料連線 http]一樣,這是最快的,但是通常,為了避免資料差錯,會對檔案傳輸內容進行分塊傳輸,並加入校驗.這就影響到了傳輸效率. 你說一輛公共汽車是從起點到終點直達快?還是一站站的停過去快?很明顯,第乙個假設脫離實際的.

關於udp可靠傳輸和cpu的關係,有嗎?肯定有,但是在普通應用下,基本沒影響,只有在追求極限,例如本機測試,2g+光釺網路等,才會有明顯的影響,可問題是,如果你的伺服器[電腦]接入的是2g+光釺,你這伺服器得什麼硬體配置? 在一般應用下,cpu和記憶體開銷以及錯誤的丟包重傳才是第一位的. 如果乙個udp可靠傳輸,100mbps網路下,必須要intel piii 1ghz以上,那在這個基礎上開發出來的應用可能比現在的電腦遊戲還離譜了.  如果不是多對多[因為這個邏輯比普通點對點udp可靠傳輸複雜的太多],普通的點對點udp可靠傳輸, 給幾個以前的測試資料, qtudp ,環境是pentium m 1.7g[單核心], ati xpress主機板 768m ddr2 533[單通道] , 本機器模擬傳輸當時測試的資料大約在 78mb/s , mtu=1380 , 緩衝是 17 * mtu.  , cpu開銷大約是75%, 如果使用目前雙核心,估計可以翻倍. 你可能會覺得這個數字太低,但是請注意當時的硬體環境,這個速度已經超過udt好多好多了. 最基本的點對點udp可靠傳輸,標準crc32校驗,以目前的硬體環境, i74核心, ddr3 1600 , 加上我們的一種特殊包處理技術,本機器udp小包[1400]可靠傳輸的極限大約在270mb/s,如果還要提公升,估計只能和ms 的iis一樣,編寫網路驅動了,但是x86處理器和記憶體速度始終在提公升,說不定明天主頻直接翻倍了...

其實,我轉向udp可靠傳輸的乙個非常重要原因,是ipv6取消了傳輸中ip層的資料校驗,這導致tcp層完全負擔起了資料校驗任務,tcp資料是否還象ipv4下那麼可靠,需要加個問號了,雖然ip層本身的差錯率非常低,但是取消掉校驗,直接帶來的風險到底有多大,並沒有經過實踐的評估,靠ipv6實驗網路得出的是理論結果,也許有一天會出現一種突破性的ipv6 tcp偽造技術. 而如果採用udp可靠傳輸,由於udp本身有校驗,加上我們自己設計的校驗和序列號,這個可靠程度完全超過了ipv4 下的tcp,更別提ipv6下的tcp了.

udp可靠傳輸,其實非常簡單,只要你有tcp/ip的基礎,最簡單的點對點udp可靠傳輸是非常容易編寫的,無非就是封包,校驗,傳送,確認,重新組包,介面可以模仿tcp的幾個函式,這其中的乙個難點是,判斷是否需要重發,這需要根據以前包的確認時間來推導本包,如果你不希望那麼複雜,也可以,經驗數字 [不適合網通到電信], 第一次的重傳時間 750 ms , 第二次是 1600 , 以後每次都是 2000 , 雖然不科學,但是用這個延遲數字,可以保證你足夠的傳輸效率[即使存在小概率丟包],也不會產生大量的重傳,當然最好的方法是從之前包的延遲來推導. 

總之,udp可靠傳輸沒那麼複雜和神秘,它非常簡單,而且,它的效率也沒有各位想象中的那麼高,可能會讓各位失望,但是,它很可愛,你可以隨意的塑造你自己的包,實現各種擴充套件,其中的取捨完全在於聰明的你.

UDP可靠傳輸那些事

有空來論壇走走,發現討論udp可靠傳輸又熱了起來,有人認為udp高效率,有人認為udp丟包重傳機制容易控制,還有朋友搞極限測試,當然也有人推銷自己的東西,這裡寫一點我個人的看法。udp可靠傳輸其實非常非常的簡單,我最開始接觸udp可靠傳輸大約是在2005年,因為那時候開發ftpanywhere,由於...

UDP可靠傳輸那些事

udp可靠傳輸其實非常非常的簡單,我最開始接觸udp可靠傳輸大約是在2005年,因為那時候開發ftpanywhere,由於路由的對映和閘道器nat處理方面,認為udp具有天生優勢,因此開始編寫自己的udp可靠傳輸協議,好象那個時候已經有了udt,我也下了源 看了下,不過很快就看不下去了,因為它用了定...

UDP實現可靠傳輸

如何讓udp實現可靠傳輸 自定義通訊協議,在應用層定義一些可靠的協議,比如檢測包的順序,重複包等問題,如果沒有收到對方的ack,重新發包 udp沒有delievery garuantee,也沒有順序保證,所以如果你要求你的資料傳送與接受既要高效,又要保證有序,收包確認等,你就需要在udp協議上構建自...