客戶端代碼:
package udp;
import java.net.*;
import java.util.*;
public class SimpleUDPClient {
public static void main(String[] args) {
DatagramSocket ds = null;
DatagramPacket sendDp, receiveDp;
String serverHost = "127.0.0.1";
int serverPort = 10010;
try {
ds = new DatagramSocket();
Date d = new Date();
String content = d.toString();
byte[] data = content.getBytes();
InetAddress address = InetAddress.getByName(serverHost);
sendDp = new DatagramPacket(data, data.length, address, serverPort);
ds.send(sendDp);
byte[] b = new byte[1024];
receiveDp = new DatagramPacket(b, b.length);
ds.receive(receiveDp);
byte[] response = receiveDp.getData();
int len = receiveDp.getLength();
String s = new String(response, 0, len);
System.out.println("服務器端回饋為:" + s);
} catch (Exception e) { e.printStackTrace(); }
finally { try { ds.close(); } catch (Exception e) {} }
}
}
流程:建立連接 → 獲取本地時間 → 構造發送包含地址端口的 DatagramPacket → 發送 → 構造接收包 → 接收回饋 → 輸出 → 關閉。
服務端代碼:
package udp;
import java.net.*;
public class SimpleUDPServer {
public static void main(String[] args) {
DatagramSocket ds = null;
DatagramPacket sendDp, receiveDp;
final int PORT = 10010;
try {
ds = new DatagramSocket(PORT);
System.out.println("服務器端已啟動:");
byte[] b = new byte[1024];
receiveDp = new DatagramPacket(b, b.length);
ds.receive(receiveDp);
InetAddress clientIP = receiveDp.getAddress();
int clientPort = receiveDp.getPort();
byte[] data = receiveDp.getData();
int len = receiveDp.getLength();
System.out.println("客戶端IP:" + clientIP.getHostAddress());
System.out.println("客戶端端口:" + clientPort);
System.out.println("客戶端發送內容:" + new String(data, 0, len));
String response = "OK";
byte[] bData = response.getBytes();
sendDp = new DatagramPacket(bData, bData.length, clientIP, clientPort);
ds.send(sendDp);
} catch (Exception e) { e.printStackTrace(); }
finally { try { ds.close(); } catch (Exception e) {} }
}
}
服務端監聽端口,receive 阻塞等待數據。收到後提取客戶端 IP/端口、輸出內容,回饋 "OK"。同樣存在客戶端無法多次交換、服務端不支援多客戶端問題。
UDP 不建立虛擬連接,最大特點是「無狀態」:服務端僅從數據包獲取信息,無法識別發送者身份,要求發送內容攜帶更多標識信息。
原理同 TCP:客戶端循環發送/接收,服務端循環接收並啟動線程處理每個包。
package udp;
import java.net.*;
import java.util.*;
public class MulUDPClient {
public static void main(String[] args) {
DatagramSocket ds = null;
DatagramPacket sendDp, receiveDp;
String serverHost = "127.0.0.1";
int serverPort = 10012;
try {
ds = new DatagramSocket();
InetAddress address = InetAddress.getByName(serverHost);
byte[] b = new byte[1024];
receiveDp = new DatagramPacket(b, b.length);
System.out.println("客戶端准備完成");
for (int i = 0; i < 30; i++) {
Date d = new Date();
String content = d.toString();
byte[] data = content.getBytes();
sendDp = new DatagramPacket(data, data.length, address, serverPort);
ds.send(sendDp);
Thread.sleep(10);
ds.receive(receiveDp);
byte[] response = receiveDp.getData();
int len = receiveDp.getLength();
String s = new String(response, 0, len);
System.out.println("服務器端回饋為:" + s);
}
} catch (Exception e) { e.printStackTrace(); }
finally { try { ds.close(); } catch (Exception e) {} }
}
}
循環 30 次發送時間,間隔 10ms,每次接收回饋。
package udp;
import java.net.*;
public class MulUDPServer {
public static void main(String[] args) {
DatagramSocket ds = null;
DatagramPacket receiveDp;
final int PORT = 10012;
byte[] b = new byte[1024];
receiveDp = new DatagramPacket(b, b.length);
try {
ds = new DatagramSocket(PORT);
System.out.println("服務器端已啟動:");
while (true) {
ds.receive(receiveDp);
new LogicThread(ds, receiveDp);
}
} catch (Exception e) { e.printStackTrace(); }
finally { try { ds.close(); } catch (Exception e) {} }
}
}
主循環接收包,啟動 LogicThread 處理。
package udp;
import java.net.*;
public class LogicThread extends Thread {
DatagramSocket ds;
DatagramPacket dp;
public LogicThread(DatagramSocket ds, DatagramPacket dp) {
this.ds = ds; this.dp = dp; start();
}
public void run() {
try {
byte[] data = dp.getData();
int len = dp.getLength();
InetAddress clientAddress = dp.getAddress();
int clientPort = dp.getPort();
System.out.println("客戶端IP:" + clientAddress.getHostAddress());
System.out.println("客戶端端口號:" + clientPort);
System.out.println("客戶端發送內容:" + new String(data, 0, len));
byte[] b = "OK".getBytes();
DatagramPacket sendDp = new DatagramPacket(b, b.length, clientAddress, clientPort);
ds.send(sendDp);
} catch (Exception e) { e.printStackTrace(); }
}
}
線程處理單次 UDP 通訊,輸出信息並回饋 "OK"。因 UDP 可能丟包導致阻塞,生產環境建議發送端也採用線程。