伺服器架構設計
public class MultiThreadServer {
static final int PORT = 9090;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
System.out.println("伺服器啟動,監聽埠 " + PORT);
ExecutorService pool = Executors.newCachedThreadPool();
while (true) {
Socket client = server.accept();
pool.submit(new ClientSession(client));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientSession implements Runnable {
private Socket socket;
ClientSession(Socket s) { socket = s; }
public void run() {
try (BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
out.println("歡迎連線!目前時間: " + new Date());
out.println("輸入 HELP 查看指令,QUIT 離開");
String cmd;
while ((cmd = in.readLine()) != null) {
cmd = cmd.trim().toUpperCase();
if (cmd.equals("QUIT")) break;
else if (cmd.equals("HELP")) {
out.println("QUERY - 查詢資料");
out.println("TIME - 顯示時間");
out.println("QUIT - 斷開連線");
} else if (cmd.startsWith("QUERY")) {
out.println("查詢結果: 模擬資料...");
} else if (cmd.equals("TIME")) {
out.println("伺服器時間: " + new Date());
} else {
out.println("未知指令,輸入 HELP 查看幫助");
}
}
} catch (IOException e) {
// 連線異常中斷
} finally {
System.out.println("客戶端斷開: " + socket.getInetAddress());
}
}
}
關鍵技術點
- 執行緒池:
Executors.newCachedThreadPool() 自動回收閒置執行緒
- 指令處理:大小寫不敏感、支援參數解析
- 資源管理:try-with-resources 自動關閉流與 Socket
- 編碼處理:InputStreamReader 指定 charset 避免亂碼
進階擴充:資料庫連線池整合
// 在 ClientSession 中使用連線池
DataSource ds = HikariConfig...; // 連線池
try (Connection conn = ds.getConnection()) {
// 執行 SQL,連線用完自動歸還池中
}
同步處理注意事項
- 共享資料需
synchronized 或 Lock 保護
- 資料庫操作建議使用連線池而非共享 Connection
- 長時間查詢應支援取消/逾時機制
測試方式
telnet localhost 9090
# 或
nc localhost 9090