1. 程式人生 > 實用技巧 >詳解UDP協議

詳解UDP協議

  運輸層位於網路層之上,網路層提供了主機之間的邏輯通訊;而運輸層為執行在不同主機上的應用程式之間提供了邏輯通訊。從應用程式角度看,通過邏輯通訊,執行不同程式的主機好像直接相連一樣。應用程式使用運輸層提供的邏輯通訊功能來傳送報文,無需考慮承載這些報文的物理基礎設施的細節,就像我們知道的透明傳輸。

  UDP是傳輸層協議的一種,也叫做使用者資料報協議,提供一種不可靠、無連線的服務。當我傳送的UDP包到達目標機器後,目標機器發現 MAC 地址匹配,於是就取下來,將剩下的包傳給處理 IP 層的程式碼。把 IP 頭取下來,發現目標 IP 匹配,然後這裡面的資料包發給誰呢?我們自己知道傳送的是UDP包,那麼目標機器怎麼知道的呢?因為IP資料報裡面有個欄位是上層協議,說明瞭上層協議是TCP還是UDP ,所以目的主機根據這個資訊知道了這個包是UDP包。

  UDP的報文段結構非常簡單,首部有4個欄位組成,每個欄位佔用兩個位元組。埠號用來區分各個應用程式,每個應用程式需要監聽一個埠,不能衝突。目標機器根據目的埠號晶資料交給相應的應用程式。長度欄位的意思是UDP首部加上應用資料的總長度。校驗和主要是接收方檢查在該報文段是否出現了差錯。應用資料就是應用層包了。

 UDP協議具有三大特點,通過上面對報文段結構的分析,也能猜到一兩個。

  • 溝通簡單,UDP協議預設包在網路中很容易送達,不容易丟棄。所以它沒有設定複雜的欄位結構、處理邏輯等。
  • 傳輸便捷,傳輸時不會建立連線,誰都可以傳給它資料,它也可以給任何人傳資料,支援同時給多人傳資料。
  • 不做調整,這裡的意思是UDP不會根據網路的情況進行發包的擁塞控制,不論網路丟包程度,它都正常傳送。

 基於這些特點,UDP主要有三大使用場景。

  • 需要資源少,在網路情況比較好的內網,或者對於丟包不敏感的應用。比如DHCP就是基於UDP協議的,一般的獲取 IP 地址都是內網請求,而且一次獲取不到IP可以過會再獲取。
  • 不需要一對一溝通建立連線,而是可以廣播的應用。由於無連線特性,可以承載很多廣播和多播協議。比如上面說的DHCP就是通過廣播的方式來發包。對於多播,主要是D類IP地址即組播地址,使用這個地址可以將包組播給一批機器。當一臺機器上的某個程式想監聽某個組播地址的時候,需要傳送 IGMP 包,所在網路的路由器就能收到這個包,知道有個機器上有個程式在監聽這個組播地址。當路由器收到這個組播地址的時候,會將包轉發給這臺機器,這樣就實現了跨路由器的組播。
  • 需要處理速度快,時延低,可以容忍少數丟包,但是要求即便網路擁塞,也繼續發包的情況。

所以,如果開發人員選擇UDP協議開發應用程式,那應用程式差不多就是直接和IP層打交道。UDP從應用程式得到資料,附加上首部欄位形成報文段交給網路層。網路層將該運輸層報文段封裝到一個IP資料報中,然偶盡最大努力交給目的主機。如果目的主機收到該資料報,UDP使用目的埠號將報文段中的資料交付給正確的應用程式。

  由於UDP 十分簡單,基本啥都沒做,如果應用是基於UDP開發的,那麼就可以有很多自主擴充套件的東西。我們通過具體的例子說明:

  1. 網頁或者 APP 的訪問,原來訪問網頁和手機 APP 都是基於 HTTP 協議的。HTTP 協議是基於 TCP 的,建立連線需要多次互動,建立一次連線需要的時間會比較長,TCP 可能還會斷了重連,也是很耗時的。而Google 提出了一種基於 UDP 改進的通訊協議QUIC(Quick UDP Internet Connections,快速 UDP 網際網路連線),其目的是降低網路通訊的延遲,提供更好的使用者互動體驗。QUIC 在應用層上,會自己實現快速連線建立、減少重傳時延,自適應擁塞控制。
  2. 流媒體的協議,現在直播比較火,直播協議多使用 RTMP。RTMP 協議也是基於 TCP 的。TCP 的嚴格順序傳輸要保證前一個收到了,下一個才能確認,如果前一個收不到,下一個就算包已經收到了,在快取裡面,也需要等著。直播對實時性要求高,寧可丟包,也不能卡頓。關於丟包。其實對於視訊播放來講,有的包可以丟,有的包不能丟。因為視訊的連續幀裡面,有的幀重要,有的不重要,如果必須要丟包,隔幾個幀丟一個,其實看視訊的人不會感知,但是如果連續丟幀,就會感知了,因而在網路不好的情況下,應用希望選擇性的丟幀。

    還有當網路不好的時候,TCP 協議會主動降低傳送速度,這對本來當時就卡頓的視訊來講是要命的,應該讓應用層馬上重傳,而不是主動讓步。因而,很多直播應用,都基於 UDP 實現了自己的視訊傳輸協議。

  3. 實時遊戲,實時遊戲中客戶端和服務端要建立長連線,來保證實時傳輸。但是遊戲玩家很多,伺服器卻不多。由於維護 TCP 連線需要在核心維護一些資料結構,因而一臺機器能夠支撐的 TCP 連線數目是有限的。 UDP 由於是沒有連線的,在非同步 IO 機制引入之前,常常是應對海量客戶端連線的策略。

    如果使用TCP協議,它的強順序性會帶來一些問題。對戰的遊戲,對網路的要求很簡單,玩家通過客戶端給伺服器傳送滑鼠和鍵盤行走的位置,伺服器會處理每個使用者傳送過來的所有場景,處理完再返回給客戶端,客戶端解析響應,渲染最新的場景展示給玩家。如果出現一個資料包丟失,所有事情都需要停下來等待這個資料包重發。客戶端會出現接收資料,然而玩家並不關心過期的資料,激戰中卡 1 秒,等能動了已經死了。

    遊戲對實時要求較為嚴格的情況下,採用自定義的可靠 UDP 協議,自定義重傳策略,能夠把丟包產生的延遲降到最低,儘量減少網路問題對遊戲性造成的影響。

  4. IoT 物聯網,一方面,物聯網領域終端資源少,很可能只是個記憶體非常小的嵌入式系統,而維護 TCP 協議代價太大;另一方面,物聯網對實時性要求也很高,而 TCP 還是因為上面的那些原因導致時延大。Google 旗下的Nest 建立 Thread Group,推出了物聯網通訊協議 Thread,就是基於 UDP 協議的。
  5. 行動通訊領域,在 4G 網路裡,移動流量上網的資料面對的協議 GTP-U 是基於 UDP 的。因為行動網路協議比較複雜,而 GTP 協議本身就包含複雜的手機上線下線的通訊協議。如果基於 TCP,TCP 的機制就顯得非常多餘。

  參考資料:《趣談網路協議》劉超

       《計算機網路:自頂向下方法》原書第六版 陳鳴譯