經典一對一阻塞 I/O 模型:
ServerSocket.accept() 阻塞等待連接,獲得 Socket 後雙向收發文本行。new Socket(host, port) 主動連接,雙向收發文本行。\n 為邊界,輸入 end 結束會話。package com.fan.socket;
import java.io.*;
import java.net.*;
public class SocketService {
public static void main(String[] args) {
new SocketService().startServer();
}
public void startServer() {
try (ServerSocket server = new ServerSocket(4800)) {
System.out.println("Server 啟動,監聽 4800...");
try (Socket client = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("Client 已連接: " + client.getInetAddress());
String line;
// 先讀客戶端第一條
System.out.println("Client: " + in.readLine());
// 主循環:控制台讀入 → 發送給客戶端 → 讀客戶端回覆
while ((line = console.readLine()) != null) {
if ("end".equalsIgnoreCase(line)) break;
out.println(line);
System.out.println("Server: " + line);
System.out.println("Client: " + in.readLine());
}
}
} catch (IOException e) {
System.err.println("Server 異常: " + e.getMessage());
}
}
}
package com.fan.socket;
import java.io.*;
import java.net.*;
public class SocketClient {
public static void main(String[] args) {
try (Socket socket = new Socket("127.0.0.1", 4800);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("Client 啟動,連接 Server...");
String line;
while ((line = console.readLine()) != null) {
if ("end".equalsIgnoreCase(line)) break;
out.println(line);
System.out.println("Client: " + line);
System.out.println("Server: " + in.readLine());
}
} catch (IOException e) {
System.err.println("Client 異常: " + e.getMessage());
}
}
}
# Terminal 1: Server
Server 啟動,監聽 4800...
Client 已連接: /127.0.0.1
Client: Hello Server
Server: Hi Client
Client: How are you?
Server: Fine, thanks
Client: end
# Terminal 2: Client
Client 啟動,連接 Server...
Client: Hello Server
Server: Hi Client
Client: How are you?
Server: Fine, thanks
Client: end
| 點 | 說明 |
|---|---|
| PrintWriter(autoFlush=true) | 構造函數第二參數 true 使 println 自動 flush,避免緩衝導致對端收不到數據 |
| try-with-resources | JDK 7+ 自動關閉流與 Socket,異常時也能釋放資源 |
| 阻塞模型限制 | 單線程只能服務一個客戶端;生產環境需多線程/線程池或 NIO (Netty) |
| 協議設計 | 文本行協議簡單但無法傳輸二進制/含換行符數據;實際項目建議定長/分隔符/序列化協議 |