java.net 包下的 DatagramSocket 與 DatagramPacket 是 Java 實現 UDP 通信的核心類。UDP 無連接、不可靠、無序,但延遲低、開銷小,適合即時遊戲、視頻流、日誌傳輸等容忍丟包但極度敏感延遲的場景。本文從核心 API 到完整收發示例,帶你快速上手 UDP 編程。
| 構造方法 | 說明 |
|---|---|
DatagramSocket() | 綁定本地任意空閒端口 |
DatagramSocket(int port) | 綁定指定本地端口 |
DatagramSocket(int port, InetAddress addr) | 綁定指定 IP 與端口(多網卡場景) |
DatagramSocket(SocketAddress bindaddr) | 綁定 SocketAddress |
核心方法:send(DatagramPacket) 發送、receive(DatagramPacket) 阻塞接收、close() 釋放端口。
| 構造類型 | 構造方法 | 用途 |
|---|---|---|
| 接收 | DatagramPacket(byte[] buf, int length) | 分配緩衝區等待接收 |
DatagramPacket(byte[] buf, int offset, int length) | 指定緩衝區偏移與長度 | |
| 發送 | DatagramPacket(byte[] buf, int length, InetAddress addr, int port) | 指定目標 IP/端口 |
DatagramPacket(byte[] buf, int length, SocketAddress addr) | 指定 SocketAddress |
常用獲取器:getData()、getLength()、getAddress()、getPort()、getSocketAddress()。
public class Getter {
public static void main(String[] args) {
try (DatagramSocket socket = new DatagramSocket(8888, InetAddress.getLocalHost())) {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); // 阻塞等待
String msg = new String(packet.getData(), 0, packet.getLength());
System.out.println("收到消息:" + msg);
System.out.println("發送方 IP:" + packet.getAddress().getHostAddress());
System.out.println("發送方端口:" + packet.getPort());
// 回覆確認
String reply = "接收方:我收到了!";
DatagramPacket replyPacket = new DatagramPacket(
reply.getBytes(), reply.length(), packet.getSocketAddress());
socket.send(replyPacket);
} catch (Exception e) { e.printStackTrace(); }
}
}
public class Sender {
public static void main(String[] args) {
try (DatagramSocket socket = new DatagramSocket()) { // 隨機端口
String msg = "你好!接收方!";
InetAddress targetIP = InetAddress.getLocalHost();
int targetPort = 8888;
DatagramPacket sendPacket = new DatagramPacket(
msg.getBytes(), msg.length(), targetIP, targetPort);
socket.send(sendPacket);
// 等待回覆
byte[] buf = new byte[1024];
DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
socket.receive(replyPacket);
System.out.println("收到回覆:" + new String(replyPacket.getData(), 0, replyPacket.getLength()));
} catch (Exception e) { e.printStackTrace(); }
}
}
Getter(監聽 8888 端口)Sender 發送數據byte[] 需足夠大(≥ MTU 通常 1500 字節),否則數據截斷DatagramSocket 實例可多線程共享收發,但單線程順序處理更簡單生產環境建議封裝:定義協議幀(魔數+長度+序號+校驗+負載)、實現簡易 ACK/重傳、引入 Netty 的 DatagramChannel 獲得異步非阻塞能力、配合 SO_RCVBUF/SO_SNDBUF 調優內核緩衝區。