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

Android Socket TCP 通訊:解決僅能接收一次數據後程式崩潰的問題

     編輯:程式設計綜合問答

問題現象

在 Android 應用中使用 Socket 進行 TCP 通訊時,開發者常遇到一個棘手的問題:客戶端成功連接伺服器並接收第一條訊息後,當伺服器發送第二條訊息時,應用程式卻直接崩潰退出,且無明顯錯誤日誌輸出。

程式碼分析

典型的問題程式碼結構如下:

Thread aa = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            client = new Socket(InetAddress.getByName("192.168.1.101"), 4312);
            BufferedReader read = new BufferedReader(new InputStreamReader(client.getInputStream()));
            rec.setText("123"); // UI 更新需在主執行緒
            String s = "";
            while (true) {
                s = read.readLine(); // 阻塞等待數據
                rec.setText(s);      // 直接在子執行緒更新 UI
            }
        } catch (IOException e) {
            rec.setText("123123");
        }
    }
});
aa.start();

核心原因

  1. 非主執行緒更新 UI:`rec.setText(s)` 在子執行緒中直接操作 `TextView`,違反 Android 單執行緒模型,導致應用崩潰。
  2. 缺乏空數據/斷開連線處理:`readLine()` 返回 `null` 時表示串流結束(對方關閉連線),若不判斷直接傳給 `setText` 會拋出異常。
  3. 網路操作在主執行緒:雖然此處用了子執行緒,但若在 `onCreate` 中直接進行耗時連線操作,仍可能導致 ANR。

解決方案

1. 使用 Handler 或 runOnUiThread 更新 UI

while (true) {
    String s = read.readLine();
    if (s == null) break; // 對方關閉連線
    final String msg = s;
    runOnUiThread(() -> rec.setText(msg));
}

2. 完善異常捕獲與資源釋放

try (Socket socket = new Socket(...);
     BufferedReader reader = new BufferedReader(...)) {
    String line;
    while ((line = reader.readLine()) != null) {
        // 處理數據
    }
} catch (IOException e) {
    Log.e("Socket", "通訊異常", e);
} finally {
    // 確保關閉資源
}

3. 採用成熟網路框架

建議使用 OkHttp、Netty 或 Android 官方推薦的 `Socket` 封裝庫,自動處理重連、心跳、執行緒切換等細節,降低出錯機率。

最佳實踐總結

  • 所有網路 I/O 操作必須在子執行緒執行。
  • UI 更新必須切換到主執行緒(`runOnUiThread`、`Handler`、`LiveData` 等)。
  • 讀取串流時務必判斷 `null`,妥善處理斷開連線情況。
  • 使用 `try-with-resources` 確保 `Socket`、`Reader` 等資源及時釋放。
  • 生產環境優先選用成熟網路框架,避免重複造輪子。

掌握上述要點,即可徹底解決 Android Socket TCP 通訊「只能收一次訊息就崩潰」的問題,構建穩定可靠的網路通訊模組。

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