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

Java Socket `Connection reset` 錯誤深度排查:客戶端未正確關閉流與伺服端讀取條件錯誤

     編輯:程式設計綜合問答

錯誤堆疊

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(...)
    at Server.receive(Server.java:34)

兩大核心錯誤

1. 客戶端未關閉輸出流與 Socket

原始碼:

writer.write("我是");
writer.newLine();
writer.flush();
// 缺少 writer.close(); socket.close();

導致伺服端 readLine() 讀到流末尾(EOF)前,客戶端進程結束,作業系統發送 RST 封包強制斷開,伺服端拋出 Connection reset。

2. 伺服端 `while` 讀取條件錯誤

原始碼:

while ((str = reader.readLine()).length() > 0) { ... }

readLine() 遇到流關閉返回 null,而非空字串。呼叫 null.length() 拋出 NullPointerException,導致執行緒異常終止,Socket 未正常關閉,進一步加劇連線重置。

修正後程式碼

客戶端

public class Client {
    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
            writer.write("我是");
            writer.newLine();
            writer.flush();
        } // try-with-resources 自動關閉 writer & socket
    }
}

伺服端

private void receive() {
    try (Socket socket = server.accept();
         BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
        StringBuilder msg = new StringBuilder();
        String str;
        while ((str = reader.readLine()) != null) {  // 正確判斷 null
            msg.append(str).append("\r\n");
        }
        System.out.println(msg.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

最佳實踐總結

  • 永遠使用 try-with-resources(Java 7+)確保流與 Socket 確定性關閉。
  • 讀取迴圈條件統一用 (line = reader.readLine()) != null。
  • 生產環境建議採用 Netty、Mina 等高階網路框架,自動處理半包/黏包、心跳、重連。
  • 瀏覽器訪問不報錯,因為 HTTP 協議有明確的 Content-Length 或 Connection: close,瀏覽器會正確關閉連線。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved