Java java.net 包提供了 ServerSocket(服務端)與 Socket(客戶端)兩大核心類,支撐雙向流式通訊。本文通過一個完整的「客戶端-服務端」多線程Demo,演示如何實現:多用戶同時在線、消息廣播、上下線通知、簡易黑名單等核心群聊功能。代碼結構清晰,適合初學者理解網絡編程與多線程協作模式。
accept() 阻塞等待連接,每來一個客戶端啟動一個 HandleSocket 線程處理該連接;維護一個 List<Socket> 存儲所有在線客戶端,集合操作加 synchronized 保證線程安全。ClientSend(從控制台讀取輸入發送)與 ClientReceive(循環讀取服務端推送並打印),主線程不退出以保持長連接。public class Server {
public static void main(String[] args) throws IOException, InterruptedException {
List<Socket> online = new ArrayList<>();
ServerSocket server = new ServerSocket(10000);
while (true) {
Socket socket = server.accept(); // 阻塞等待連接
synchronized (online) { online.add(socket); } // 線程安全加入列表
new HandleSocket(socket, online).start(); // 啟動處理線程
}
}
}
public class HandleSocket extends Thread {
private Socket socket;
private List<Socket> online;
public HandleSocket(Socket socket, List<Socket> online) {
this.socket = socket; this.online = online;
}
@Override public void run() {
String ip = socket.getInetAddress().getHostAddress();
System.out.println(ip + " 上線了!");
// 簡易黑名單演示
if (ip.equals("192.168.1.117")) {
synchronized (online) {
sendToAll(ip + " 因違規被拉黑!");
online.remove(socket);
}
return;
}
try (BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream(), "GBK"))) {
String line;
while ((line = br.readLine()) != null) {
String msg = ip + ": " + line;
System.out.println(msg); // 服務端控制台顯示
sendToAll(msg); // 廣播給其他客戶端
}
} catch (IOException e) {
System.out.println(ip + " 下線了!");
synchronized (online) { online.remove(socket); }
}
}
/** 廣播消息給除發送者外的所有在線客戶端 */
private void sendToAll(String msg) {
synchronized (online) {
for (Socket s : online) {
if (s != socket) {
try { new PrintStream(s.getOutputStream()).println(msg); }
catch (IOException ignored) {}
}
}
}
}
}
// 發送線程
public class ClientSend extends Thread {
private Socket socket;
public ClientSend(Socket socket) { this.socket = socket; }
@Override public void run() {
try (PrintStream ps = new PrintStream(socket.getOutputStream());
Scanner sc = new Scanner(System.in)) {
String line;
while ((line = sc.nextLine()) != null) ps.println(line);
} catch (IOException e) { e.printStackTrace(); }
}
}
// 接收線程
public class ClientReceive extends Thread {
private Socket socket;
public ClientReceive(Socket socket) { this.socket = socket; }
@Override public void run() {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) System.out.println(line);
} catch (Exception e) { e.printStackTrace(); }
}
}
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.1.188", 10000); // 修改為實際服務端 IP
new ClientSend(socket).start();
new ClientReceive(socket).start();
// 主線程不退出,保持長連接
}
}
Server.main(),控制台顯示等待連接;Client.main()(可在不同機器/進程),分別輸入用戶名/消息;IP 上線了!、IP: 消息內容、IP 下線了!;synchronized(online) 保護增刪改查;GBK,避免中文亂碼(客戶端默認 UTF-8 需統一);IOException 統一處理下線邏輯。進階擴展建議:引入協議幀(如 JSON/Protobuf)區分聊天/私聊/文件/心跳;使用 NIO/Netty 替換 BIO 提升併發上限;加入用戶認證、群組管理、消息持久化、離線推送等。
com.dragon.java.tcpchat ├── Server.java ├── HandleSocket.java ├── Client.java ├── ClientSend.java └── ClientReceive.java
這是一個「弱小但完整」的局域網群聊原型,通過親手敲碼、跑通流程,能快速建立起「Socket 通訊 + 多線程協作 + 共享狀態同步」的核心心智模型,為後續學習 Netty、即時通訊架構打下堅實基礎。