本文記錄一個基於 UDP 協定的簡易聊天室實作,採用純文字介面(DOS/Console),適合初學者理解 Java 網路程式設計核心概念。專案包含伺服器端與多客戶端,支援使用者註冊、身分驗證、指定對象私聊與廣播訊息。
java.net.DatagramSocket:UDP 通訊端點java.net.DatagramPacket:資料封包封裝java.net.SocketAddress / InetSocketAddress:對端位址java.util.Hashtable:執行緒安全的使用者資訊登記表java.util.Enumeration:遍歷線上使用者java.util.Scanner:主控台輸入讀取receive(packet) 監聽埠口SocketAddress 為鍵存入 Hashtable(暱稱、IP、Port)@REG# 註冊、@MSG# 訊息、@QUIT# 下線)分派處理send() 給各客戶端Hashtable<SocketAddress, UserInfo> userRegistry = new Hashtable<>();
class UserInfo {
String nickname;
SocketAddress address;
long lastActiveTime;
}
| 指令 | 格式 | 說明 |
|---|---|---|
| 註冊 | @REG#暱稱 | 客戶端首次送出,伺服器回覆 @ACK# 或 @NAK# |
| 廣播 | @MSG#ALL#內容 | 伺服器轉發給所有線上使用者 |
| 私聊 | @MSG#目標暱稱#內容 | 伺服器查表轉發給指定對象 |
| 下線 | @QUIT# | 伺服器移除登記並廣播下線通知 |
receive(),解析伺服器推送訊息並印至主控台Scanner 讀取使用者輸入,封裝協定送出DatagramSocket(自動指派隨機本地埠)@REG#暱稱 至伺服器固定 IP:Portpublic class ChatServer {
private static final int PORT = 8888;
private static Hashtable<InetSocketAddress, UserInfo> users = new Hashtable<>();
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(PORT);
byte[] buf = new byte[1024];
while (true) {
DatagramPacket pkt = new DatagramPacket(buf, buf.length);
socket.receive(pkt);
String msg = new String(pkt.getData(), 0, pkt.getLength(), "UTF-8");
handleMessage(socket, pkt.getSocketAddress(), msg);
}
}
private static void handleMessage(DatagramSocket s, SocketAddress from, String msg) {
if (msg.startsWith("@REG#")) { register(from, msg.substring(5)); }
else if (msg.startsWith("@MSG#")) { dispatch(s, from, msg); }
else if (msg.startsWith("@QUIT#")) { unregister(from); }
}
private static void broadcast(DatagramSocket s, String text, SocketAddress exclude) throws IOException {
byte[] data = text.getBytes("UTF-8");
for (SocketAddress addr : users.keySet()) {
if (!addr.equals(exclude)) {
s.send(new DatagramPacket(data, data.length, addr));
}
}
}
}
public class ChatClient {
private static final String SERVER_IP = "127.0.0.1";
private static final int SERVER_PORT = 8888;
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
InetSocketAddress server = new InetSocketAddress(SERVER_IP, SERVER_PORT);
// 註冊
String nick = new Scanner(System.in).nextLine();
send(socket, server, "@REG#" + nick);
// 接收執行緒
new Thread(() -> {
byte[] buf = new byte[1024];
while (true) {
DatagramPacket pkt = new DatagramPacket(buf, buf.length);
socket.receive(pkt);
System.out.println(new String(pkt.getData(), 0, pkt.getLength(), "UTF-8"));
}
}).start();
// 主迴圈發送
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String line = sc.nextLine();
send(socket, server, "@MSG#ALL#" + line);
}
}
private static void send(DatagramSocket s, InetSocketAddress to, String text) throws IOException {
byte[] data = text.getBytes("UTF-8");
s.send(new DatagramPacket(data, data.length, to));
}
}
@PING# 檢測離線,避免殭屍連線透過 DatagramSocket 與 Hashtable 即可快速建構 UDP 聊天室雛形。專案雖簡單,卻涵蓋網路程式設計的核心要素:協定設計、並發存取、位址管理、封包收發。建議初學者先跑通 DOS 版本,再逐步引入可靠性保障與圖形介面。