深入的理解UDP程式設計 星辰大海

2022-09-23 07:06:07 字數 3075 閱讀 2192

什麼是udp?

udp是user datagram protocol(使用者資料報協議)的縮寫,它是乙個簡單的協議,簡單到udp規範rfc0768只有區區3頁。

udp是工作在ip層之上的傳輸層協議,udp對ip主要有兩個擴充套件:

擴充套件出埠號使得ip資料報可以多路分發到使用者程序。擴充套件出校驗和提供網路傳輸過程中資料差錯的檢驗。ip提供了一種盡力而為、無連線的資料報交付服務。ip基於ip位址實現路由和分組**,可以將乙個ip資料報從網路的一台主機傳送到另一台主機,ip位址決定ip資料報將被送往哪個主機。所以,ip提供主機到主機的資料報傳輸服務。

ip資料報到達目的主機後,核心層實現的ip模組,會負責接收網絡卡上的ip資料報,但主機上通常會同時執行多個程序,ip資料報應該交給哪個程序去處理呢?ip搞不定。

埠號(位於udp首部)決定資料報交給主機上的哪個程序處理。所以,udp為端主機上執行的應用程式提供了端到端服務。

udp的特徵

udp是無連線的,通訊之前無須建連便可直接傳送資料報,而tcp是面向連線的。udp不提供差錯糾正,但udp提供差錯檢測(端到端校驗和)。udp不做重複消除。udp不做流量控制。udp不做擁塞控制,沒有協議機制防止高速udp流量對其他網路使用者的消極影響。udp不保證順序,資料報遞交應用的順序。udp不可靠,udp只負責把應用程式傳給ip層的資料傳送出去,並不能保證資料報到達目的地,可靠傳遞需要應用程式去實現。udp支援組播交付。udp是一種保留訊息邊界的傳輸層協議。

訊息邊界

應用程式每請求一次udp輸出將產生乙個udp資料報,從而傳送乙個ip資料報,而接收端每請求一次udp接收都將接收乙個完整的udp報(如果有),這跟面向資料流的tcp不一樣。

假設主機a給主機b傳送2次資料,第一次4位元組「abcd」,第二次3位元組「xyz」,而主機b接收2次,分別返回「abcd」、「xyz」兩個訊息,也可以返回「xyz」,「abcd」兩個訊息(順序不重要),那麼這就是保留訊息邊界。

udp是保留訊息邊界的傳輸層協議,利用udp通訊的應用程式每次傳送操作會產生乙個ip資料報(不考慮分片),這就約束每次傳送的資料量不能大於mtu(最大傳輸單元),接收端每次接收都會返回乙個個udp資料報的完整負載,不會出現返回半個資料報負載的情況。

而tcp是不保留訊息邊界的流協議,傳送端呼叫傳送的次數和每次傳送的資料量,跟接收端呼叫接收的次數和每次接收的資料量,沒有任何對應關係,所以使用tcp的應用程式需要去處理訊息邊界。

udp資料報封裝格式

ipv4協議(protocol)欄位用值17來標識udp,udp資料報頭部通常是8位元組,ipv4頭部之後緊接著是udp頭部,然後是udp資料payload(如有)。

ipv4封裝包對應的udp頭部由源埠號、目的埠號、長度、校驗和組成,每個欄位都是2位元組。1、埠號,純抽象的標識,它不跟任何物理實體相關埠號用於幫助協議分辨傳送和接收程序。接收端的核心層從網絡卡接收到ip資料報之後,識別出udp資料報(ip資料報頭部協議字段值=17)之後,會根據udp頭部的目的埠號,對映到對應程序,把udp資料報交給對應的程序去處理,這個對映關係由系統核心管理維護。

目的埠號是必須的,但源埠號是可選的,如果資料報傳送者不需要對方回覆的話,則源埠號可被設定為0。

因為ip層根據ip頭部的協議型別字段,將進入的ip資料報,分發到特定的傳輸協議(tcp或udp等),到了傳輸協議層,再根據埠號將協議資料分發到不同程序。所以,埠號是協議獨立的,不同協議的相同埠號並不會引起分發混亂。

比如,一台機器上的兩個網路服務程序使用相同的ip位址和埠號,但乙個使用tcp協議,另乙個使用udp協議,這樣是沒有問題。

2、長度字段,是以位元組為單位的udp頭部和udp資料的總長度,因為udp頭部長度為8,且空資料的udp資料報是允許的,這意味著該長度字段值最小為8。udp長度值是冗餘的,因為可以通過ip資料報的總長度減去ip首部的長度推導出來。

3、校驗和,覆蓋了udp首部、udp資料和乙個偽首部,由初始傳送方計算,由最終目的方校驗,用於判斷資料報在網路傳輸過程中是否出錯,比如某一位從1變成了0。

使用udp的應用程式如何實現可靠傳輸

眾所周知,udp不可靠、不保證順序。

1、什麼叫不可靠?a給b傳送乙個udp資料報,該udp資料報不一定被正確交付給接收端b,但因為網路質量等各種原因,可能丟包,ip資料報是盡力而為的交付,一切隨緣。

有沒有辦法保證,傳送的udp一定到達目的端?sorry,保證不了,做不到。

那tcp提供的可靠傳輸是什麼意思?tcp提供的可靠傳輸並不是指不丟包,因為tcp也依賴ip(ip不可靠)實現資料報交付,tcp的可靠性是指丟掉的包會被重傳,直到被正確投遞,才會繼續傳輸下乙個資料報。

那tcp是怎麼做到可靠傳輸的呢?很簡單,收報確認(ack)+丟包重傳。所以udp如果要提供可靠傳輸,也可以參考tcp的實現機制,只是tcp是實現在核心層,而基於udp的應用程式,可以把可靠傳輸做到應用層。要做收報確認+丟包重傳,需要一些額外的資訊,比如包序列號之類,可以放到payload,約定好這些額外資訊在payload中的結構布局即可。

2、什麼叫不保證順序?a給b傳送兩個udp資料報,兩個udp資料報會被封裝為兩個ip資料報,通過ip協議傳輸,因為兩個ip資料報獨立路由,所以哪個先到?不一定,看心情。

有沒有辦法保證,udp資料報按照傳送端傳送的時間順序到達目的端?也sorry,辦不到。

所以,tcp提供的順序性,其實只是在接收端對ip資料報根據傳送順序重新排序,很顯然,udp要支援重排序,也需要一些額外資訊,也只能通過payload攜帶,而不能像tcp一樣(tcp首部的一些字段用於接收端重排序)。

綜上,udp只提供最簡單端主機上應用程式的端到端服務,其他的特性,如果要提供,那請參考tcp的思路去實現吧。

這是有好處的:因為簡單,所以開銷很小。而某些應用場景,可以容忍丟包、亂序,udp就是很適合的。保時捷是很好,但拉磚還是用拖拉機吧。

udp socket網路程式設計的api不多,socket()用於建立套接字,close()用於關閉套接字,sendto()用於傳送資料,recvfrom()用於接收資料。

bind()顧名思義是繫結,tcp可以繫結,udp也可以,bind用於udp等於告訴核心:這個套接字跟網路遠端的乙個

而沒有bind之前,只能通過sendto()介面(通過引數指定目的地)。udp套接字recv()返回的是udp資料報的資料部分(payload),不包括udp資料報首部,這是因為udp首部的字段用於分發或者校驗,不需要透傳給應用程式。

Linux在實際中的應用 星辰大海

linux在實際中的應用 各位童鞋們,你們是如何度過這周週末的呢?這週末的我在家學習學習再學習,然而學習到一半,公司領導突然給我打了個 過來說有同事等會兒會去客戶那部署無人值守安裝系統服務,問我去不去學習下。我想我正在學linux,雖然還沒學習到那個部分,但是提前接觸下對後面學習肯定會有很大幫助,所...

陳年的凡客征途注定是星辰和大海

春天的邀請萬物都答應 說不得的只有我的愛情 穆旦 一封情書 尚未遠去,陳年的愛情再度回歸,這是我們熟悉的陳年,也是我們期待的凡客。這是我們熟悉的文藝凡客,但是伴隨凡客長大的人已不再年輕。4月,如約而來,凡客的新年t恤上線,新標語為 只有上帝知道,我有多愛你 文藝t恤是凡客文藝范的詮釋,這次新產品的定...

vijos訓練之 星辰大海中閃爍的趣題

看到難度普遍7 9就感覺很勁 再加上doc出品,於是果斷入坑。由於知識性內容還沒有學完,只能慢慢刷了。這sb題居然智障wa了兩次 由於是回文串只要列舉前半段,然後瞎幾把測試素數就好了。順便學習一波miller rabin的二次探查。複雜度o n slgn s為測試次數。include using n...