首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 網絡編程基礎 (三):DatagramSocket 與 DatagramPacket 實現 UDP 通信

     編輯:Java 相關知識

UDP (User Datagram Protocol) 是無連接、不可靠、保留消息邊界的傳輸協議。Java 用 DatagramSocket (發送/接收端點) + DatagramPacket (數據容器) 實現。本文詳細講解:構造器、發送接收流程、地址/端口處理、端口掃描實戰、常見坑點。

核心類速覽

類關鍵構造/方法說明
DatagramSocketnew DatagramSocket() (隨機端口) / new DatagramSocket(port) (指定端口) / new DatagramSocket(port, InetAddress) (指定網卡) / send(p) / receive(p) / close()UDP 端點,綁定本地端口
DatagramPacketnew DatagramPacket(buf, len) (接收) / new DatagramPacket(buf, len, addr, port) (發送) / getAddress() / getPort() / getData() / getLength() / setLength()數據報容器,攜帶數據、目標/來源地址端口
InetAddressgetByName(host) / getHostAddress()IP 地址封裝

發送流程

// 1. 創建 Socket (發送端通常用隨機端口)
try (DatagramSocket socket = new DatagramSocket()) {
    // 2. 準備數據
    String msg = "Hello UDP";
    byte[] data = msg.getBytes(StandardCharsets.UTF_8);
    
    // 3. 解析目標地址
    InetAddress target = InetAddress.getByName("192.168.1.100");
    int port = 9000;
    
    // 4. 構建發送包 (含目標地址端口)
    DatagramPacket packet = new DatagramPacket(data, data.length, target, port);
    
    // 5. 發送
    socket.send(packet);
    System.out.println("已發送至 " + target + ":" + port);
}

接收流程

// 1. 創建 Socket 綁定固定端口 (接收端必須固定端口)
try (DatagramSocket socket = new DatagramSocket(9000)) {
    byte[] buffer = new byte[4096]; // 足夠大緩衝區
    
    while (true) {
        // 2. 構建接收包 (無目標地址)
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        
        // 3. 阻塞接收
        socket.receive(packet); // 此處阻塞直到有數據報到達
        
        // 4. 解析數據
        String msg = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8);
        InetAddress sender = packet.getAddress();
        int senderPort = packet.getPort();
        
        System.out.printf("收自 %s:%d → %s%n", sender.getHostAddress(), senderPort, msg);
        
        // 5. 重置長度供下次接收 (關鍵!)
        packet.setLength(buffer.length);
    }
}

實戰:UDP 端口掃描器

public class UdpPortScanner {
    public static void main(String[] args) {
        String target = "127.0.0.1";
        int startPort = 1024, endPort = 65535;
        int openCount = 0;
        
        for (int port = startPort; port <= endPort; port++) {
            try (DatagramSocket socket = new DatagramSocket(port)) {
                // 能綁定說明端口空閒
                socket.close();
            } catch (SocketException e) {
                // 綁定失敗 = 端口被佔用
                System.out.println("端口佔用: " + port);
                openCount++;
            }
        }
        System.out.println("掃描完成,共發現 " + openCount + " 個佔用端口");
    }
}

原理:new DatagramSocket(port) 嘗試綁定端口,成功 = 空閒,失敗拋 SocketException = 被佔用。注意:需 socket.close() 釋放,否則後續端口無法綁定。

DatagramPacket 關鍵方法詳解

方法發送包含義接收包含義
getAddress()目標 IP發送方 IP
getPort()目標端口發送方端口
getData()待發送字節數組接收到的字節數組 (含舊數據,需配合 getLength())
getLength()發送字節數實際接收字節數
setLength(int)設置發送長度必須重置為緩衝區長度,否則下次只能接收 ≤ 上次長度

關鍵坑點與最佳實踐

  1. 緩衝區大小:接收端緩衝區 ≥ 最大預期數據報 (通常 4096-65507),超出部分會被靜默丟棄。
  2. MTU 限制:以太網 MTU 1500,扣除 IP/UDP 頭部,單數據報建議 ≤ 1472 字節,大數據需應用層分片。
  3. 無連接 = 無狀態:發送端不關心對方是否在線,接收端不確認收到。需可靠性請用 TCP 或應用層實現 ACK/重傳。
  4. 廣播/組播:socket.setBroadcast(true) + 發送至 255.255.255.255 (廣播) 或組播地址 224.0.0.0/4。
  5. 編碼顯式化:StandardCharsets.UTF_8,跨平台無亂碼。
  6. 防火牆:UDP 易被攔截,部署時需放行雙向端口。

總結

UDP 通信核心:DatagramSocket 綁定端口、DatagramPacket 封裝數據與地址、send/receive 雙向交互、setLength 重置緩衝區。適用場景:DNS、NTP、視頻流、心跳、日誌傳輸、服務發現。掌握「不可靠」本質,在應用層按需補償可靠性,是用好 UDP 的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved