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

Java UDP 協議程式設計入門:InetAddress、DatagramSocket 與 DatagramPacket 實戰

     編輯:Java 相關知識

前言

Java java.net 套件封裝了網路協議細節,使 UDP 程式設計相對簡單。本文從核心類別入手,構建完整的 C/S 模式時間服務範例。

核心類別速覽

InetAddress:IP 位址封裝

  • 無公開建構子,透過靜態工廠方法取得實例
  • getByName(String host):域名/IP → 單一位址
  • getAllByName(String host):域名 → 位址陣列
  • getLocalHost():本機位址
  • getHostAddress():取得 IP 字串
InetAddress ia = InetAddress.getByName("compaq"); // 主機名
String ip = ia.getHostAddress(); // 取得 IP
// localhost → 127.0.0.1

DatagramPacket:資料封包

發送用建構子 (含目標位址/埠口):

  • DatagramPacket(byte[] buf, int length, InetAddress addr, int port)
  • DatagramPacket(byte[] buf, int offset, int length, InetAddress addr, int port)
  • DatagramPacket(byte[] buf, int length, SocketAddress addr)

接收用建構子 (無目標位址):

  • DatagramPacket(byte[] buf, int length)
  • DatagramPacket(byte[] buf, int offset, int length)

關鍵方法:getData() 取得位元組陣列,getLength()/getOffset() 取得有效範圍,getAddress()/getPort() 取得來源位址。

DatagramSocket:收發端點

  • DatagramSocket():客戶端,臨時埠口
  • DatagramSocket(int port):伺服器,固定埠口
  • DatagramSocket(int port, InetAddress addr):多網卡指定綁定
  • 核心方法:send()、receive() (阻塞)、setSoTimeout()、close()
  • 建構子可能拋 SocketException (埠口衝突),必須捕獲

完整範例:UDP 時間服務 (埠口 13)

伺服器端 TimeServer.java

import java.io.*;
import java.net.*;
import java.util.*;

public class TimeServer {
    final private static int DAYTIME_PORT = 13;

    public static void main(String args[]) throws IOException {
        DatagramSocket socket = new DatagramSocket(DAYTIME_PORT);
        System.out.println("Time Server listening on port " + DAYTIME_PORT);

        while (true) {
            byte buffer[] = new byte[256];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            socket.receive(packet); // 阻塞等待請求

            String date = new Date().toString();
            buffer = date.getBytes();

            // 從請求封包取得客戶端位址/埠口
            InetAddress address = packet.getAddress();
            int port = packet.getPort();

            // 回覆封包
            packet = new DatagramPacket(buffer, buffer.length, address, port);
            socket.send(packet);
        }
    }
}

客戶端 GetTime.java

import java.io.*;
import java.net.*;

public class GetTime {
    final private static int DAYTIME_PORT = 13;

    public static void main(String args[]) throws IOException {
        if (args.length == 0) {
            System.err.println("Usage: java GetTime ");
            System.exit(-1);
        }

        String host = args[0];
        byte message[] = new byte[256];
        InetAddress address = InetAddress.getByName(host);
        System.out.println("Querying: " + address);

        // 發送請求 (空資料即可觸發伺服器回覆)
        DatagramPacket packet = new DatagramPacket(message, message.length, address, DAYTIME_PORT);
        DatagramSocket socket = new DatagramSocket(); // 臨時埠口
        socket.send(packet);

        // 接收回覆
        packet = new DatagramPacket(message, message.length);
        socket.receive(packet);

        String time = new String(packet.getData(), 0, packet.getLength());
        System.out.println("Time at " + host + " is: " + time);
        socket.close();
    }
}

編譯與執行

javac TimeServer.java GetTime.java
# 終端機 1 啟動伺服器
java TimeServer
# 終端機 2 執行客戶端
java GetTime localhost

進階補充:常見坑點與最佳實踐

議題說明
封包大小限制理論 65,507 位元組,實務建議 ≤ 8KB 避免 IP 分片丟包
阻塞模型receive() 永久阻塞,生產環境必設 setSoTimeout() 或使用 NIO DatagramChannel
埠口衝突啟動前檢查埠口佔用,捕獲 SocketException
資料編碼位元組陣列轉字串需指定編碼:new String(data, 0, len, StandardCharsets.UTF_8)
防火牆/NATUDP 易被封鎖,需開放對應埠口;NAT 穿透需 STUN/TURN/ICE
可靠性補強應用層加入序號、ACK、重傳、FEC (視訊常用)
廣播/多播socket.setBroadcast(true) + 255.255.255.255;多播用 MulticastSocket + joinGroup()

總結

Java UDP 程式設計核心在於 DatagramSocket (端點) 與 DatagramPacket (封包) 的配合。掌握無連線特性、阻塞模型、封包大小限制與異常處理,即可開發高效的即時網路應用。

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