TCP 提供可靠、有序、面向連接的字節流服務。Java java.net.Socket(客戶端)與 ServerSocket(服務端)是阻塞式 I/O (BIO) 基礎。本文提供最小可運行的雙端代碼、關鍵步驟解析、資源管理最佳實踐。
public class TcpClient {
public static void main(String[] args) throws IOException {
String host = "192.168.1.100";
int port = 10002;
try (Socket socket = new Socket(host, port);
OutputStream out = socket.getOutputStream()) {
String msg = "TCP 測試:客戶端發送數據";
out.write(msg.getBytes(StandardCharsets.UTF_8));
out.flush(); // 確保發送緩衝區刷新
} // try-with-resources 自動關閉 socket 與流
}
}
public class TcpServer {
public static void main(String[] args) throws IOException {
int port = 10002;
try (ServerSocket server = new ServerSocket(port)) {
System.out.println("服務端啟動,監聽端口 " + port);
while (true) { // 循環接受多個客戶端
try (Socket client = server.accept();
InputStream in = client.getInputStream()) {
String ip = client.getInetAddress().getHostAddress();
byte[] buf = new byte[1024];
int len = in.read(buf); // 阻塞直到有數據或連接關閉
if (len > 0) {
String msg = new String(buf, 0, len, StandardCharsets.UTF_8);
System.out.printf("%s: %s%n", ip, msg);
}
} catch (IOException e) {
System.err.println("客戶端處理異常: " + e.getMessage());
}
}
}
}
}
Socket。ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(() -> handle(client));LengthFieldBasedFrameDecoder (Netty) 或自寫 readFully 讀取長度前綴。socket.setSoTimeout(ms) 或 Netty IdleStateHandler。shutdownOutput() 發送 FIN,繼續讀取對端剩餘數據。SSLServerSocketFactory / SSLSocketFactory。| 現象 | 原因 | 對策 |
|---|---|---|
| read() 返回 -1 | 對端關閉輸出流 (EOF) | 視為連接結束,跳出讀取循環 |
| 中文亂碼 | 編碼不一致 | 雙端統一 StandardCharsets.UTF_8 |
| 發送大數據卡住 | 發送緩衝區滿 | 分塊發送、檢查 sendBufferSize |
| 端口佔用 | TIME_WAIT 狀態 | server.setReuseAddress(true) |
BIO 模式下,ServerSocket.accept() 循環 + 線程池處理 + try-with-resources 管理資源 是 Java TCP 服務端的標準模板。理解「流是無邊界字節序列,應用層必須定義協議幀」是避免粘包/半包的關鍵。