基於 TCP Socket 實現客戶端發送請求、服務端處理後主動回覆的完整流程。關鍵點在於雙方正確關閉輸出流(shutdownOutput())以觸發對端 readLine() 返回 null 結束讀取循環。
package com.socket.demo;
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8888)) {
System.out.println("----------------服務端啟動,監聽 8888 端口----------------");
Socket socket = serverSocket.accept();
System.out.println("客戶端連接:" + socket.getInetAddress());
// 1. 讀取請求
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("收到請求:" + line);
}
}
// 關閉輸入流,表示讀取完畢
socket.shutdownInput();
// 2. 發送回覆
try (PrintWriter writer = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true)) {
writer.println("服務端已收到您的消息,處理完成。");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.socket.demo;
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
try (Socket socket = new Socket("127.0.0.1", 8888)) {
// 1. 發送請求
try (PrintWriter writer = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true)) {
writer.println("客戶端請求:你好,服務端!");
}
// 關鍵:關閉輸出流,通知服務端請求結束
socket.shutdownOutput();
// 2. 讀取回覆
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("服務端回覆:" + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
| 操作 | 作用 | 缺失後果 |
|---|---|---|
socket.shutdownOutput() (Client) | 發送 FIN 包,服務端 readLine() 返回 null 跳出循環 | 服務端永久阻塞在讀取循環 |
socket.shutdownInput() (Server) | 發送 FIN 包,客戶端 readLine() 返回 null 跳出循環 | 客戶端永久阻塞在讀取循環 |
PrintWriter(..., true) | 啟用自動 flush,println 後自動發送 | 需手動 flush(),否則數據滯留緩衝區 |
| try-with-resources | 自動關閉流與 Socket,釋放文件描述符 | 資源洩漏,端口佔用 |
readLine() 永不返回 null,線程掛起。shutdownOutput + 等待對端 ACK 後關閉 Socket。