僅依賴 JDK java.net 標準庫,無需第三方框架,適合輕量級、特定協議的通訊場景。
public class TcpServer {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(0)) { // 0 = 自動分配端口
System.out.println("Server listen on: " + serverSocket.getLocalPort());
boolean running = true;
while (running) {
try (Socket clientSocket = serverSocket.accept();
DataInputStream in = new DataInputStream(
new BufferedInputStream(clientSocket.getInputStream()));
PrintStream out = new PrintStream(
new BufferedOutputStream(clientSocket.getOutputStream()))) {
// === 業務處理邏輯 ===
String request = in.readUTF();
String response = processRequest(request);
out.println(response);
out.flush();
} catch (IOException e) {
System.err.println("Client handling error: " + e.getMessage());
}
}
} catch (IOException e) {
System.err.println("Server fatal: " + e.getMessage());
}
}
private static String processRequest(String req) {
// 實際業務邏輯
return "ECHO: " + req;
}
}
public class TcpClient {
public static void main(String[] args) {
String host = "localhost";
int port = 12345; // 需與服務端一致
try (Socket socket = new Socket(host, port);
DataInputStream in = new DataInputStream(socket.getInputStream());
PrintStream out = new PrintStream(socket.getOutputStream())) {
out.println("Hello Server");
out.flush();
String response = in.readUTF();
System.out.println("Server reply: " + response);
} catch (IOException e) {
System.err.println("Client error: " + e.getMessage());
}
}
}
| 環節 | 說明 |
|---|---|
| 流包裝順序 | Socket.getInputStream() → BufferedInputStream → DataInputStream (讀取基本類型/UTF)Socket.getOutputStream() → BufferedOutputStream → PrintStream (文本行輸出) |
| 緩衝必要性 | 減少系統調用次數,提升吞吐;必須手動 flush() 確保數據發送 |
| 字符編碼 | PrintStream 默認平台編碼,跨平台建議顯式指定 new PrintStream(out, true, "UTF-8") |
| 阻塞特性 | accept()、read() 默認阻塞,單線程只能串行處理 |
| 優雅關閉 | try-with-resources 自動關閉流與 Socket,釋放端口資源 |
ExecutorService 接收任務,每連接一線程 (適合連接數 < 500)Selector + ServerSocketChannel 單線程管理萬級連接 (Netty/Mina 封裝)選型建議:教學/原型/極簡場景用原生 Socket;生產系統直接上 Netty/gRPC,專注業務而非通訊基建。