首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Socket 網絡編程完整示例:服務端與客戶端雙向通信

     編輯:Java 相關知識

架構概覽

  • ServerSocket:服務端監聽端口,accept() 阻塞等待客戶端連接
  • Socket:雙方通信端點,通過 getInputStream()/getOutputStream() 讀寫數據
  • 線程模型:每連接一線程 (示例) / 線程池 / NIO 選擇器 (生產級)

服務端實現


public class EchoServer {
    private static final int PORT = 8888;

    public static void main(String[] args) throws IOException {
        try (ServerSocket server = new ServerSocket(PORT)) {
            server.setReuseAddress(true);
            System.out.println("服務端啟動,監聽端口: " + PORT);

            ExecutorService pool = Executors.newCachedThreadPool(); // 簡單線程池

            while (true) {
                Socket client = server.accept(); // 阻塞
                InetAddress addr = client.getInetAddress();
                System.out.println("新連接: " + addr.getHostAddress() + ":" + client.getPort());

                pool.execute(() -> handleClient(client, addr));
            }
        }
    }

    private static void handleClient(Socket socket, InetAddress addr) {
        try (socket;
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
             PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true)) {

            String line;
            while ((line = in.readLine()) != null) {
                System.out.println("收自 " + addr + ": " + line);
                if ("bye".equalsIgnoreCase(line.trim())) {
                    out.println("Goodbye!");
                    break;
                }
                // 業務邏輯: 回聲 + 時間戳
                out.println("Echo: " + line + " [" + Instant.now() + "]");
            }
        } catch (IOException e) {
            System.err.println("客戶端 " + addr + " 異常斷開: " + e.getMessage());
        } finally {
            System.out.println("連接關閉: " + addr);
        }
    }
}

客戶端實現


public class EchoClient {
    private static final String HOST = "localhost";
    private static final int PORT = 8888;

    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket(HOST, PORT);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
             PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
             BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {

            System.out.println("已連接到服務端,輸入 'bye' 退出");
            String input;
            while ((input = console.readLine()) != null) {
                out.println(input); // 發送
                String response = in.readLine(); // 同步等待響應
                if (response == null) {
                    System.out.println("服務端已關閉連接");
                    break;
                }
                System.out.println("服務端回覆: " + response);
                if ("Goodbye!".equals(response)) break;
            }
        }
    }
}

關鍵技術點深度解析

1. 字符流 vs 字節流

  • 文本協議:BufferedReader/PrintWriter + 指定 StandardCharsets.UTF_8,自動處理換行符
  • 二進制協議:直接使用 InputStream/OutputStream 或 DataInputStream/DataOutputStream

2. 半包/粘包問題 (TCP 流式特性)

現象:發送 "ABC" "DEF",接收可能讀到 "AB" "CDEF" 或 "ABCDEF"。

解決方案:

  1. 定長:固定每條消息長度 (如 1024 字節)
  2. 分隔符:換行符 \n、\r\n 或特殊字符 (示例採用 readLine() 隱含換行符)
  3. 長度前綴:[4字節長度][消息體],最通用高效
  4. 序列化框架:Protobuf、MessagePack、Hessian 內建幀邊界

3. 線程模型演進

模型適用場景Java 實現
每連接一線程連接數 < 500、低併發new Thread() / CachedThreadPool
固定線程池連接數穩定、CPU 密集業務FixedThreadPool
NIO 非阻塞 (Reactor)高併發、長連接、IO 密集Selector / Netty / Mina
虛擬線程 (Java 21+)高併發、代碼同步寫法Executors.newVirtualThreadPerTaskExecutor()

4. 優雅關閉與資源管理

  • 使用 try-with-resources 確保 Socket/Stream 關閉
  • 服務端關閉時:serverSocket.close() 觸發 accept() 拋出 SocketException,退出循環
  • 設置 SO_LINGER / SO_TIMEOUT 避免僵死連接

生產級增強清單

  1. 心跳機制:空閒 30 秒發送 PING,超過 3 次無響應斷開
  2. 協議封裝:定義 Magic + Length + Type + Payload + Checksum 二進制幀
  3. 編解碼器:ByteToMessageDecoder / MessageToByteEncoder (Netty)
  4. SSL/TLS:SSLServerSocketFactory / SSLSocketFactory 加密傳輸
  5. 連接池/負載均衡:客戶端維護連接池,服務端接入 Nginx/HAProxy

總結

Java Socket API 設計經典,掌握 阻塞 IO 基礎模型、字符/二進制協議選擇、半包粘包處理、線程模型權衡、資源安全釋放 五大核心,即可構建健壯的網絡應用。現代項目建議直接使用 Netty 或 Java 21 虛擬線程,專注業務邏輯而非底層 IO 複雜度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved