| 構造器 | 參數說明 | 適用場景 |
ServerSocket(int port) | port=0 表示 OS 自動分配空閒埠 | 最簡單用法,預設 backlog=50 |
ServerSocket(int port, int backlog) | backlog:內核等待隊列最大長度(未完成三次交握+已完成未 accept) | 高併發場景調大(如 1024) |
ServerSocket(int port, int backlog, InetAddress bindAddr) | bindAddr:多網卡/多 IP 機器指定綁定介面;null 綁定所有 | 多介面服務隔離、安全區域綁定 |
常見異常:BindException(埠已佔用)、SecurityException(特權埠<1024 無權限)。
核心方法
Socket accept():阻塞等待客戶端連線,返回新 Socket。可設 setSoTimeout(ms) 避免永久阻塞。
void close():關閉監聽,釋放埠口。
InetAddress getInetAddress() / int getLocalPort():查詢綁定資訊。
void setSoTimeout(int timeout):設定 accept() 超時,超時拋 SocketTimeoutException。
static void setSocketFactory(SocketImplFactory fac):全域自定義 Socket 實現(極少用)。
經典多執行緒伺服器模式
public class ThreadPerClientServer {
private final ExecutorService pool = Executors.newFixedThreadPool(100);
public void start(int port) {
try (ServerSocket server = new ServerSocket(port)) {
server.setSoTimeout(1000); // 定期檢查關閉標誌
while (!Thread.currentThread().isInterrupted()) {
try {
Socket client = server.accept();
pool.submit(() -> handleClient(client));
} catch (SocketTimeoutException ignored) {}
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
pool.shutdown();
}
}
private void handleClient(Socket socket) {
try (socket;
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String line;
while ((line = in.readLine()) != null) {
out.println("Echo: " + line);
}
} catch (IOException e) {
log.error("Client error", e);
}
}
}
線程池優化:固定大小 + 有界隊列 + 拒絕策略
ExecutorService pool = new ThreadPoolExecutor(
50, 200, // core / max
60L, TimeUnit.SECONDS, // keepAlive
new LinkedBlockingQueue<>(1000), // 有界隊列防 OOM
new ThreadFactoryBuilder().setNameFormat("server-worker-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略:呼叫執行緒執行,自然限流
);
遷移至 NIO:為何與如何
| 痛點 | BIO 線程池 | NIO Reactor |
| C10K 併發 | 執行緒數線性增長,記憶體/上下文切換崩潰 | 少量執行緒輪詢萬級連線 |
| 閒置連線 | 每連線佔一執行緒(即使無資料) | 無資料無事件,零 CPU 佔用 |
| 擴展性 | 受限於作業系統執行緒上限 | 單機輕鬆 50K+,配合多 Reactor 更高 |
遷移關鍵步驟
ServerSocketChannel.open().configureBlocking(false)
Selector.open() + serverChannel.register(selector, OP_ACCEPT)
- 事件迴圈
while(selector.select() > 0) 處理 OP_ACCEPT/OP_READ/OP_WRITE
- 引入
ByteBuffer、協議編解碼器、半包處理
- 生產建議:直接使用 Netty,避免重複造輪子。
生產級檢查清單
- [ ] 埠口衝突處理(啟動檢查、優雅降級)
- [ ] 連線超時:
SO_TIMEOUT (accept/read) + 應用層心跳
- [ ] 緩衝區大小調優:
SO_RCVBUF/SO_SNDBUF 配合 BDP
- [ ] 優雅關閉:攔截 SIGTERM,停止 accept、等待任務完成、關閉線程池、關閉 ServerSocket
- [ ] 監控指標:活躍連線數、隊列積壓、執行緒池狀態、錯誤率
- [ ] 安全:TLS (SSLServerSocket)、存取控制、速率限制
總結
ServerSocket 是 Java 阻塞式 TCP 伺服端的基石。理解其構造器參數、accept() 語義、線程池整合模式,是進階掌握 Netty 等高效能框架的前置知識。現代高併發系統應儘早遷移至 NIO/Netty 架構。
- 上一篇文章: Java Socket 類深度解析:構造器、核心方法、連線建立與 I/O 流操作實戰
- 下一篇文章: 零基礎邁向 Java 高手完整學習路徑:環境搭建、核心語法、Web 全棧與主流框架
Copyright ©
程式碼之家 All Rights Reserved