You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单线程TCP Server安卓APP需客户端断开才接收消息问题求助

问题分析与解决方案

问题根源

  • readLine()的阻塞特性:BufferedReader.readLine()会一直阻塞,直到读取到**换行符(\n或\r\n)**或者输入流被关闭(客户端断开连接)才返回结果。你使用的测试客户端发送消息时没有追加换行符,导致服务器一直处于等待状态,直到客户端断开连接、流结束,才一次性返回所有累积的消息。
  • 单连接仅读取一次:当前代码在接收到Socket连接后,只执行一次readLine()就回到serverSocket.accept(),无法处理同一个客户端发送的多条消息,因为没有循环读取该Socket的输入流。

修复方案

1. 为每个连接单独启动线程循环读取消息

主服务器线程仅负责监听新连接,每个连接的消息读取逻辑放到独立线程中,既避免阻塞新连接的建立,又能持续读取该客户端的消息。

2. 确保消息以换行结尾(或改用非行读取方式)

要么要求客户端发送消息时追加换行符,要么改用read()方法读取字节流,自行约定消息边界(比如固定长度、特定分隔符)。

修正后的代码示例

Thread tcpServerThread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(65000);
            while (true) {
                // 阻塞等待新连接建立
                Socket socket = serverSocket.accept();
                handler.post(() -> Toast.makeText(getApplicationContext(), "NEW CONNECTION", Toast.LENGTH_SHORT).show());

                // 为每个连接启动独立线程处理消息读取
                new Thread(() -> {
                    try (BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                        String receivedMsg;
                        // 循环读取,直到输入流关闭(客户端断开)
                        while ((receivedMsg = input.readLine()) != null) {
                            Message msg = new Message(MessageMakerInterface.makeMessage(receivedMsg), Message.MSG_RECIEVED);
                            messageList.add(msg);
                            handler.post(() -> {
                                adapter.notifyDataSetChanged();
                                rvChat.scrollToPosition(messageList.size() - 1);
                            });
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});
tcpServerThread.start();

补充说明

  • 使用try-with-resources语法自动关闭BufferedReader,避免资源泄漏。
  • 每个连接的处理线程独立,主服务器线程可继续监听新连接,同时单个客户端的多条消息能被实时读取(只要每条消息末尾带换行符)。
  • 如果客户端无法添加换行符,可替换readLine()为逐字节读取,自行处理消息拆分:
    char[] buffer = new char[1024];
    int len;
    while ((len = input.read(buffer)) != -1) {
        String receivedMsg = new String(buffer, 0, len);
        // 此处添加消息处理逻辑
    }
    

内容的提问来源于stack exchange,提问作者Lookyus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:20:45