近期深入研究 Java Socket 網路通訊基礎,動手實作一個支援多用戶同時線上聊天的即時通訊室。這裡將完整的專案架構、核心程式碼與執行步驟分享給有興趣的開發者參考,希望能幫助大家快速掌握 Socket 程式設計的精髓。
專案採用標準 Maven 結構,主要分為客戶端與伺服器端兩大模組:

客戶端採用 AWT 圖形介面,包含訊息顯示區、輸入框,並使用獨立執行緒持續監聽伺服器推送的訊息。
package com.panda.chat;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
@SuppressWarnings("serial")
public class ChatClient extends Frame {
private TextArea ta = new TextArea();
private TextField tf = new TextField();
private DataOutputStream dos = null;
private DataInputStream dis = null;
private Socket socket = null;
private boolean bConnected = false;
private Thread thread = null;
public static void main(String[] args) {
new ChatClient().frameClient();
}
public void frameClient() {
setSize(400, 400);
setLocation(400, 300);
add(ta, BorderLayout.NORTH);
add(tf, BorderLayout.SOUTH);
pack();
tf.addActionListener(new TfListener());
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
disconnected();
System.exit(0);
}
});
this.connect();
setVisible(true);
}
private void connect() {
try {
socket = new Socket("127.0.0.1", 8888);
thread = new Thread(new ChatThread());
thread.start();
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
} catch (UnknownHostException | IOException e) {
e.printStackTrace();
}
}
private void disconnected() {
bConnected = false;
try {
if (dos != null) dos.close();
if (dis != null) dis.close();
if (socket != null) socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
private class TfListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String strMsg = tf.getText();
tf.setText("");
try {
dos.writeUTF(strMsg);
dos.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private class ChatThread implements Runnable {
@Override
public void run() {
try {
bConnected = true;
while (bConnected) {
String msg = dis.readUTF();
ta.setText(ta.getText() + msg + "\n");
}
} catch (SocketException e) {
System.out.println("連線中斷");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
伺服器端使用 ServerSocket 監聽連線,每當有新客戶端接入,即啟動一條獨立執行緒處理該客戶的收發訊息,並將收到的訊息廣播給所有已連線的客戶端。
package com.panda.chat;
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer {
private boolean started = false;
private List chatThreads = new ArrayList<>();
public static void main(String[] args) {
new ChatServer().startServer();
}
private void startServer() {
try (ServerSocket seso = new ServerSocket(8888)) {
started = true;
System.out.println("伺服器已啟動,等待客戶端連線...");
while (started) {
Socket sos = seso.accept();
System.out.println("一個客戶端已連線:" + sos.getInetAddress());
ChatThread ct = new ChatThread(sos);
chatThreads.add(ct);
new Thread(ct).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ChatThread implements Runnable {
private Socket socket;
private DataInputStream din = null;
private DataOutputStream don = null;
private boolean bConnected = false;
public ChatThread(Socket socket) {
this.socket = socket;
}
private void send(String strMsgIn) {
try {
don.writeUTF(strMsgIn);
don.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
din = new DataInputStream(socket.getInputStream());
don = new DataOutputStream(socket.getOutputStream());
bConnected = true;
while (bConnected) {
String strMsgIn = din.readUTF();
System.out.println("收到訊息:" + strMsgIn);
for (ChatThread ct : chatThreads) {
ct.send(strMsgIn);
}
}
} catch (IOException e) {
try {
socket.close();
chatThreads.remove(this);
System.out.println("客戶端斷開連線,移除執行緒");
} catch (IOException e1) {
e1.printStackTrace();
}
} finally {
try {
if (din != null) din.close();
if (don != null) don.close();
if (socket != null) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
ChatServer 主程式,控制台將顯示「伺服器已啟動...」。ChatClient 主程式,每次啟動都會彈出一個聊天視窗。
Socket 與 ServerSocket 建立可靠的雙向連線。ChatThread),實現並發處理;客戶端另闢執行緒非阻塞接收訊息。DataOutputStream/DataInputStream 進行 UTF-8 字串的高效讀寫。finally 區塊或 try-with-resources 中確保關閉串流與 Socket,避免洩漏。此範例為教學示範用途,實際生產環境可考慮:
Selector)替代傳統 BIO,提升併發承載能力。完整原始碼可依照上述結構自行建立專案,若在實作過程中遇到任何問題,歡迎留言交流探討。