首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Socket 簡單聊天程序無輸出:read(char[]) 返回值判斷錯誤導致死循環

     編輯:程式設計綜合問答

現象

客戶端發送消息,服務端收到並打印,但雙方控制台均無後續輸出,程序卡住不退出。

核心 Bug:int len = -1 初始化錯誤

// 錯誤代碼片段
char[] c = new char[2];
int len = -1; // ★ 錯誤在此
while ((len = br.read(c)) != -1) {
    sb.append(c, 0, len);
}

BufferedReader.read(char[]) 返回 實際讀取的字符數,正常情況 ≥ 0。初始化為 -1 無實質危害,但**真正問題在於協議不匹配**:

  • 發送端用 PrintStream.println() 發送帶 \n 的行文本
  • 接收端用 read(char[]) 按字符數組讀,**不識別行結束符**,會阻塞等待填滿數組或流關閉

修正方案:統一按行協議

接收端改用 BufferedReader.readLine()

// 服務端接收循環
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
String line;
while ((line = br.readLine()) != null) { // 遇到 \n 返回行內容(不含換行符)
    System.out.println("收到: " + line);
    // 業務處理...
}

發送端用 PrintWriter + autoFlush=true

PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"), true);
pw.println("消息內容"); // 自動發送 + 換行符觸發對端 readLine 返回

完整修正版代碼結構

// 客戶端
Socket s = new Socket("127.0.0.1", 8888);
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"), true);
     BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
     BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
    
    String input;
    while ((input = console.readLine()) != null) {
        pw.println(input);          // 發送
        String reply = br.readLine(); // 接收回显
        System.out.println("Server: " + reply);
    }
}

// 服務端
ServerSocket ss = new ServerSocket(8888);
while (true) {
    Socket s = ss.accept();
    new Thread(() -> {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
             PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"), true)) {
            
            String msg;
            while ((msg = br.readLine()) != null) {
                System.out.println("Client: " + msg);
                pw.println("Echo: " + msg);
            }
        } catch (IOException e) { e.printStackTrace(); }
    }).start();
}

關鍵知識點總結

API行為適用場景
read(char[])按字符數讀取,不識別行結束二進制協議/固定長度
readLine()讀取一行 (以 \n/\r\n 結尾)文本行協議 (最常用)
PrintWriter.println()發送字符串 + \n,可配置 autoFlush文本發送

「發送端 println ↔ 接收端 readLine」是文本 Socket 通信的黃金搭檔,拒絕手動拼裝字符數組與判斷 -1。

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