UDP協議詳解+代碼演示

1、UDP協議基礎

1. UDP是什么?

UDP(User Datagram Protocol,用戶數據報協議)是傳輸層的核心協議之一,與TCP并列。它的主要特點是:????

  • 無連接:通信前不需要建立連接(知道對端的IP和端口號就直接進行傳輸,不需要建立連接)

  • 不可靠:不保證數據包的順序、完整性或可達性(沒有確認機制,沒有重傳機制;如果因為網絡故障該段無法發到對方,UDP協議層也不會給應用層返回任何錯誤信息)

  • 大小受限:?次最多傳輸64k(UDP協議首部中有?個16位的最大長度.也就是說?個UDP能傳輸的數據最大長度是 64K(包含UDP首部))

  • 輕量級:頭部開銷小(僅8字節)

  • 高效:沒有TCP的握手、確認和重傳機制

2. UDP報文結構

UDP數據包(稱為數據報)由頭部和數據部分組成:

  • 源端口號(2字節):發送方端口

  • 目標端口號(2字節):接收方端口

  • 數據報長度(2字節):頭部+數據的長度

  • 校驗和(2字節):錯誤檢測(可選)如果校驗和出錯則直接丟棄

2、UDP的核心特性

1. 無連接通信:UDP不需要預先建立連接,直接發送數據報。這類似于寄信,不需要確認收件人是否在家。

2. 不可靠傳輸:UDP不提供:數據包確認機制、丟失重傳機制、數據包排序功能

3.面向數據報:每個UDP數據報都是獨立的,這與TCP的字節流模式不同

4.支持廣播和多播:UDP可以向多個主機同時發送數據:

  • 單播?:一對一

  • 廣播?:一對所有

  • 多播?:一對一組

3、基于UDP的應用層協議

  • NFS:網絡文件系統
  • TFTP:簡單文件傳輸協議
  • DHCP:動態主機配置協議
  • BOOTP:啟動協議(用于無盤設備啟動)
  • DNS:域名解析協議

當然,也包括我們自己寫UDP程序時自定義的應用層協議。

4、Java中的UDP編程

主要使用了兩個類 :

1、DatagramSocket :用于發送和接收數據報的套接字

// 創建UDP套接字(綁定隨機端口)
DatagramSocket socket = new DatagramSocket();

// 創建綁定特定端口的套接字
DatagramSocket serverSocket = new DatagramSocket(8080);

2、DatagramPacket :表示UDP數據報的容器

// 創建接收數據包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

// 創建發送數據包
String message = "Hello UDP";
byte[] data = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(
? ? data,?
? ? data.length,?
? ? InetAddress.getByName("localhost"),?
? ? 8080
);

5、完整Java UDP示例

1.Echoserver:UDP服務器,接收客戶端消息并原樣返回

package Network.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class Echoserver {//創建一個socket對象private DatagramSocket socket;//構造方法,初始化socket對象public Echoserver(int port) throws SocketException {socket = new DatagramSocket(port);}//啟動服務器,完成主要的業務邏輯public void start() throws IOException {System.out.println("服務器啟動!");while(true) {//1.接收客戶端的請求并解析//1)創建一個字節數組(DatagramPacket 對象),用于存儲接收到的數據DatagramPacket reqPacket = new DatagramPacket(new byte[4096],4096);//2)通過receive讀取網卡的數據,如果網卡沒有收到數據,就會阻塞等待socket.receive(reqPacket);//3)把DATagramPacket中的數據解析成字符串,只需要從DatagramPacket取到有效的樹即可String request = new String(reqPacket.getData(),0,reqPacket.getLength());//2.根據請求計算響應String response = process(request);//3.把響應寫回客戶端//1)把響應字符串轉成字節數組,并封裝成DatagramPacket對象DatagramPacket resPacket = new DatagramPacket(response.getBytes(),response.getBytes().length,reqPacket.getSocketAddress());//2)通過socket把DatagramPacket對象發送出去 (把DatagramPacket寫回到客戶端)socket.send(resPacket);//4.打印日志System.out.printf("[%s:%d] req: %s,resp: %s\n",reqPacket.getAddress(),reqPacket.getPort(),request,response);}}//由于是“回顯服務器”,所以響應和請求是一樣的,直接返回請求即可public String process(String request) {return request;}public static void main(String[] args) throws IOException {Echoserver server = new Echoserver(9090);server.start();          //回顯服務器完成}
}

代碼詳細解析:

①創建 EchoServer 服務端的類,定義成員變量

  • DatagramSocket:UDP通信的核心類,用于發送和接收數據報

  • 封裝在類中作為成員變量,整個生命周期內有效


②構造方法

  • 創建綁定到指定端口的 DatagramSocket(可能會拋出異常,如:該端口已被占用)

  • port 是服務器自身綁定的監聽端口號,等待客戶端發送數據,客戶端需要知道服務器的這個端口號才能向其發送消息。

  • 客戶端通過該端口找到服務器,而客戶端的端口由系統動態分配。

  • 這種設計體現了?UDP 無連接的特性,服務器只需關注自身綁定端口即可接收所有客戶端消息。


③核心業務邏輯(start方法)

  • while 無限循環接收來自客戶端的數據,這里可以根據自己的需求更改接收次數
  • 創建緩沖區:分配一個4096字節(字節大小自行定義不溢出就行)的空數組,存儲接收到的數據
  • 阻塞等待數據報到達(數據此時已存入?reqPacket?的字節數組中)如果 reqPacket 沒有接收到客戶端發來的數據這里會阻塞等待
  • 聲明 String 類型的 request 變量,將 reqPacket?中的數據解析為字符串
  1. getData() :獲取字節數組(可能包含多余的空字節)
  2. getLength() :獲取實際有效數據長度(避免解析無效字節)

在網絡編程中,將響應(response)轉成字節數組(byte[])再發送是必要的步驟,這與計算機底層的數據傳輸機制和網絡協議的特性密切相關。

  • process() :返回響應后的數據,由于整段代碼實現的是 Echo(回顯) 服務器代碼,響應內容=請求內容,所以方法中直接返回請求即可
  • soclet.send() :將數據發送回客戶端

附上發送回客戶端的終端代碼

  • 打印日志:打印客戶端信息和通信內容


④主方法

  • new Echoserver(9090) :調用構造函數,創建綁定到?9090?端口的?DatagramSocket(UDP套接字)

  • server.start() :啟動服務器循環,等待客戶端數據報



2.EchoClient:UDP客戶端,發送消息并顯示服務器返回的響應

package Network.UDP;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;public class EchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public EchoClient(String serverIp, int serverPort) throws IOException {  socket = new DatagramSocket();this.serverIp = serverIp;this.serverPort = serverPort;}   //啟動客戶端,發送數據,接收數據,關閉連接public void start() throws IOException {Scanner scanner = new Scanner(System.in);System.out.println("客戶端啟動!");while(true) {//1.從控制臺讀取要發送的數據內容(用字符串表示)System.out.print(">");String request = scanner.nextLine(); //2.構造成UDP請求,并發送.不光要填內容,還要填服務器的地址和端口號DatagramPacket reqPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort); socket.send(reqPacket);//3.接收服務器響應的數據DatagramPacket resPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(resPacket);String response = new String(resPacket.getData(),0,resPacket.getLength());//4.把響應的數據解析并打印System.out.println(response);}}public static void main(String[] args) throws IOException {EchoClient echoclient = new EchoClient("127.0.0.1",9090);echoclient.start();}
}

詳細代碼解析:

①創建 EchoClient 客戶端的類,定義成員變量

  • socket :客戶端UDP套接字

  • serverIp/serverPort :服務器地址信息

?


②構造方法

  • DatagramSocket ( )? 為客戶端隨機分配一個端口號
  • 保存服務器地址信息


③核心業務邏輯(start方法)

  • request 用戶輸入要發送的數據
  • reqPacket 封裝要發送的數據
  1. request.getBytes() :將用戶輸入的字符串轉換為字節數組
  2. request.getBytes().length :獲取字節數組的長度,表示要發送的數據大小
  3. InetAddress.getByName(serverIp) :通過服務器的IP地址獲取對應的 InetAddress 對象,表示數據要發送到的目標地址
  4. serverPort :服務器的端口號,表示數據要發送到的端口
  • socket.send() :調用 send 方法將數據報發送到指定的目標地址和端口
  • resPacket() :接收服務器發回的響應數據,socket.receive() 是一個阻塞操作,直到接收到數據才會繼續執行
  • response :提取響應內容,將接收到的字節數據轉換為字符串

④主方法

  • 創建客戶端實例,連接本地服務器的9090端口
  • start 啟動客戶端

6、UDP編程注意事項

1.數據報大小限制

  • UDP數據報最大長度理論為65535字節
  • 實際受MTU限制(通常1500字節)
  • 建議保持數據報在1472字節以內(IPv4)

2.數據邊界問題

  • 每個 receive() 調用接收一個完整的數據報
  • 不會出現TCP的“粘包”問題

3.錯誤處理

  • 網絡不可達
  • 端口未監聽
  • 數據包丟失

4.安全性考慮

  • UDP易受DDoS攻擊
  • 應考慮實現應用層的驗證機制

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77557.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77557.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77557.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于大模型的膽總管結石全流程預測與臨床應用研究報告

目錄 一、引言 1.1 研究背景 1.2 研究目的與意義 1.3 研究方法和創新點 二、大模型在膽總管結石預測中的應用原理 2.1 大模型概述 2.2 模型構建的數據來源與處理 2.3 模型訓練與優化 三、術前預測與準備 3.1 術前膽總管結石存在的預測 3.2 基于預測結果的術前檢查方…

Windows避坑部署SkyworkAI/SkyReels-V2昆侖萬維電影生成模型

#工作記錄 前言 SkyworkAI/SkyReels-V2 是由昆侖萬維開源的全球首個無限時長電影生成模型,基于擴散強迫框架結合多模態大語言模型、強化學習等技術,支持文本到視頻、圖像到視頻等多種生成方式 開源項目地址: SkyworkAI/SkyReels-V2&#x…

iVX 圖形化編程如何改寫后端開發新范式

在數字化轉型加速推進的當下,企業對后端系統的需求呈現爆發式增長。Gartner 最新報告指出,2025 年全球企業平均需完成 300 定制化應用開發,而傳統編碼模式下,單個項目平均交付周期長達 6 - 8 個月。與此同時,Redis、K…

策略模式:靈活的算法封裝與切換

策略模式是一種行為型設計模式,它將一組算法封裝成獨立的類,使它們可以相互替換。策略模式讓算法的變化獨立于使用算法的客戶端。本文將以一個收銀系統為例,詳細介紹策略模式的實現和應用。 什么是策略模式? 策略模式定義了算法…

第十四章-PHP與HTTP協議

第十四章-PHP與HTTP協議 一,HTTP 協議詳解 HTTP(HyperText Transfer Protocol,超文本傳輸協議)是互聯網上應用最廣泛的協議之一,用于客戶端(如瀏覽器)與服務器之間的通信。它是 Web 技術的基石…

刀客獨家 | 潘勝接管百度移動生態市場部

一、 據刀客doc向獨家信源確認,百度移動生態事業群(MEG)市場部日前完成重要人事調整:潘勝已經接任市場負責人。 此前,根據雷鋒網3月底的報道,百度云渠道生態總經理陳之若離職,原移動生態事業群…

Springoot、Flowable快速學習

應用背景: 公司打算做個考勤系統,涉及到請假、補卡之類的流程審批。想到了工作流,gitee、github上看了下開源的,有自研的和常見的Flowable?、Activiti?。首先放棄自研的,考慮到成熟度、社區生態,最后選擇…

關于 【Spring Boot Configuration Annotation Processor 未配置問題】 的詳細分析、解決方案及代碼示例

以下是關于 Spring Boot Configuration Annotation Processor 未配置問題 的詳細分析、解決方案及代碼示例: 1. 問題描述 當使用 Spring Boot 的配置注解(如 ConfigurationProperties、Value、ConditionalOnProperty 等)時,若未…

Spring系列四:AOP切面編程 第一部分

AOP切面編程 💗AOP-官方文檔🍝AOP 講解🍝AOP APIs 💗動態代理🍝初探動態代理🍝動態代理深入🍝AOP問題提出📗使用土方法解決📗 對土方法解耦-開發最簡單的AOP類&#x1f4…

【云計算】云計算中IaaS、PaaS、SaaS介紹

0 隨著云計算、大數據、人工智能發展迅速,布局“云”已經是互聯網企業共識。云計算的服務類型分為三種,分別為IaaS、PaaS、SaaS,這三個分別是什么意思,今天做一個簡單的介紹和了解。 一、云計算 云計算是用戶需求通過Internet獲取計算資源,把計算資源包裝成服務,提供給…

使用HYPRE庫并行裝配IJ稀疏矩陣指南: 矩陣預分配和重復利用

使用HYPRE庫并行裝配IJ稀疏矩陣指南 HYPRE是一個流行的并行求解器庫,特別適合大規模稀疏線性系統的求解。下面介紹如何并行裝配IJ格式的稀疏矩陣,包括預先分配矩陣空間和循環使用。 1. 初始化矩陣 首先需要創建并初始化一個IJ矩陣: #incl…

目標跟蹤最新文章閱讀列表

AAAI2025 TrackFormer: Multi-Object Tracking with Transformers 論文:https://arxiv.org/abs/2101.02702 代碼:https://github.com/timmeinhardt/trackformer AAAI2025 SUTrack 單目標跟蹤 論文:https://pan.baidu.com/s/10cR4tQt3lSH5V2RNf7-3gg?pwd=pks2 代碼:htt…

分布式GPU上計算長向量模的方法

分布式GPU上計算長向量模的方法 當向量分布在多個GPU卡上時,計算向量模(2-范數)需要以下步驟: 在每個GPU上計算本地數據的平方和跨GPU通信匯總所有平方和在根GPU上計算總和的平方根 實現方法 下面是一個完整的CUDA示例代碼,使用NCCL進行多…

高并發下單庫存扣減異常?飛算 JavaAI 自動化生成分布式事務解決方案

在電商、旅游等行業業務量激增,高并發下單場景中,傳統庫存扣減方式弊端盡顯。超賣問題因缺乏有效并發控制機制頻發,多個訂單同時訪問庫存數據,導致同一商品多次售出,訂單無法履約引發客戶投訴;同時&#xf…

MVCWebAPI使用FromBody接受對象的方法

近期在做軟件升級操作的時候突然想著需要的參數比較多&#xff0c;如果需要參數的話參數比較多&#xff0c;所有想著使用frombody來集合數據統一操作做了個樣張希望對您有幫助 代碼如下&#xff1a; /// <summary>/// 入口當前文件接口下的操作數據/// </summary>/…

Atlas 800I A2 離線部署 DeepSeek-R1-Distill-Llama-70B

一、環境信息 1.1、硬件信息 Atlas 800I A2 1.2、環境信息 注意&#xff1a;這里驅動固件最好用商業版&#xff0c;我這里用的社區版有點小問題 操作系統&#xff1a;openEuler 22.03 LTS NPU驅動&#xff1a;Ascend-hdk-910b-npu-driver_24.1.rc3_linux-aarch64.run NPU固…

NLP預處理:如何 處理表情符號

一、說明 本系列文總結了在NLP處理中&#xff0c;進行文本預處理的一些內容、步驟、處理工具包應用。本篇專門談論網上文章表情符號處理&#xff0c;對于初學者具有深刻學習和實驗指導意義。 二、介紹 表情符號已成為現代交流不可或缺的一部分&#xff0c;尤其是在社交媒體、…

C++/SDL 進階游戲開發 —— 雙人塔防(代號:村莊保衛戰 14)

&#x1f381;個人主頁&#xff1a;工藤新一 &#x1f50d;系列專欄&#xff1a;C面向對象&#xff08;類和對象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;終會照亮我前方的路 &#x1f389;歡迎大家點贊&#x1f44d;評論&#x1f4dd;收藏?文章 文章目錄 二…

解鎖空間數據新質生產力暨:AI(DeepSeek、ChatGPT)、Python、ArcGIS Pro多技術融合下的空間數據分析、建模與科研繪圖及論文寫作

人工智能&#xff08;AI&#xff09;與ArcGIS Pro的結合&#xff0c;為空間數據處理和分析開辟了前所未有的創新路徑。AI通過強大的數據挖掘、深度學習及自動化能力&#xff0c;可高效處理海量、多源、異構的空間數據&#xff0c;極大提升了分析效率與決策支持能力。而ArcGIS P…

18.2.go語言redis中使用lua腳本

在 Redis 中使用 Lua 腳本可以實現原子性操作、減少網絡開銷以及提高執行效率。 Redis 執行 Lua 腳本的原理 Redis 內置了 Lua 解釋器&#xff0c;能夠直接在服務器端執行 Lua 腳本。當執行 Lua 腳本時&#xff0c;Redis 會將腳本作為一個整體執行&#xff0c;保證腳本執行期…