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

Java 網絡編程中使用緩存流:BufferedInputStream/BufferedOutputStream 正確姿勢

     編輯:程式設計綜合問答

為什麼「用了緩存反而什麼都不顯示」?

Socket 通信中,緩存流 BufferedOutputStream 預設 8KB 緩衝區,**數據不會立即發送**,直到:

  • 緩衝區滿
  • 調用 flush()
  • 流關閉 close() (內部會 flush)

若客戶端寫入後不 flush(),服務端 read() 會阻塞等待數據,雙方陷入「死等」狀態,控制台無任何輸出,也無異常拋出。

正確收發模式

發送端 (必須 flush)

Socket socket = new Socket("127.0.0.1", 8888);
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

bos.write("Hello Server\n".getBytes(StandardCharsets.UTF_8));
bos.flush(); // ★ 關鍵:強制發送緩衝區數據

// 或使用 PrintWriter 自動行刷新
PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true); // true = autoFlush
pw.println("Hello Server"); // 自帶 \n 觸發 flush

接收端 (建議 BufferedReader 按行讀)

BufferedReader br = new BufferedReader(
    new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));

String line;
while ((line = br.readLine()) != null) { // 遇到 \n/\r\n 返回
    System.out.println("收到: " + line);
}

完整最小化 Demo (客戶端+服務端)

// Server.java
public class Server {
    public static void main(String[] args) throws IOException {
        try (ServerSocket ss = new ServerSocket(8888)) {
            System.out.println("Server started...");
            while (true) {
                try (Socket s = ss.accept();
                     BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
                     PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"), true)) {
                    
                    String msg = br.readLine();
                    System.out.println("Client: " + msg);
                    pw.println("Echo: " + msg); // autoFlush 發送
                }
            }
        }
    }
}

// Client.java
public class Client {
    public static void main(String[] args) throws IOException {
        try (Socket s = new Socket("127.0.0.1", 8888);
             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);
            }
        }
    }
}

避坑總結

錯誤後果修正
只用 BufferedOutputStream 不 flush數據卡在緩衝區,對端收不到每次寫完調用 flush()
用 read(byte[]) 且無協議分隔粘包/半包,業務解析錯誤按行/定長/長度前綴協議 + BufferedReader.readLine()
字符集不一致中文亂碼雙方統一 StandardCharsets.UTF_8
未關閉流/Socket資源洩漏、連接不釋放try-with-resources 自動關閉

「緩存流必須配合 flush/協議使用」是 Java 網絡編程的鐵律,掌握它能省去無數調試夜晚。

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