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

ADB端口转发实现PC与平板Socket通信需Sleep才能正常接收问题

问题原因分析

你的核心问题出在Socket流的读取/写入逻辑不匹配,结合ADB转发的流缓冲特性导致:

  1. 服务端用BufferedReader.readLine()读取数据,该方法会一直阻塞,直到读取到换行符\n或者输入流触发EOF(结束信号)。但你客户端发送的JSON字符串没有换行符,也未主动告知服务端写入结束,导致服务端永远卡在读取步骤。
  2. 添加Thread.sleep(100)后,客户端最终执行socket.close(),此时服务端输入流触发EOF,readLine()才会返回null并退出循环——这只是靠延迟关闭连接“凑巧”让服务端收到数据,并非正确的通信逻辑。
  3. flush()调用时机错误,应该在写完所有数据后立即执行,而非等到尝试读取回复之后。
解决方案

针对两端代码做以下修正:

客户端(PC)修正

  1. 在发送的JSON字符串末尾添加换行符\n,让服务端的readLine()可以识别单条消息结束。
  2. 写完数据后立即调用flush(),确保数据立刻推送到服务端。
  3. 发送完毕后调用shutdownOutput(),主动告知服务端客户端已完成写入,避免服务端无限等待。

修正后的isPortUsed方法:

public static boolean isPortUsed(String ip, int port) throws IOException {
    try (Socket socket = new Socket()) {
        socket.connect(new InetSocketAddress(ip, port));
        OutputStream os = socket.getOutputStream();
        String jsonString = "{\"name\":\"123\",\"id\":123456}\n"; // 追加换行符作为消息边界
        byte[] data = jsonString.getBytes("UTF-8");
        
        // 批量发送数据
        for (int i = 0; i < 5; i++) {
            os.write(data);
        }
        os.flush(); // 立即推送数据到服务端
        os.shutdownOutput(); // 告知服务端:客户端写入已完成

        // 读取服务端回复(恢复服务端回复逻辑后生效)
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String serverMessage = in.readLine();
        if (serverMessage != null) {
            System.out.println("服务器回复:" + serverMessage);
        }

        return true; // 端口可连接(服务端在线)
    } catch (IOException ex) {
        return false; // 端口未被占用/服务端未启动
    }
}

服务端(平板)修正

  1. 恢复服务端的回复逻辑(若需要给PC回传消息)。
  2. 回复消息时同样添加换行符,让客户端的readLine()可以正常识别。
  3. 使用try-with-resources自动管理Socket资源,避免连接泄漏。

修正后的服务端代码:

ServerSocket serverSocket = new ServerSocket(10025);
while (true) {
    try (Socket clientSocket = serverSocket.accept()) {
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String inputLine;
        
        // 读取客户端所有消息
        while ((inputLine = in.readLine()) != null) {
            Log.e("hehe", "run: " + inputLine + ", 端口:" + clientSocket.getPort());
            System.out.println("Received: " + inputLine);
        }

        // 给客户端发送回复
        OutputStream os = clientSocket.getOutputStream();
        String serverMessage = "Hello from server!";
        byte[] data = (serverMessage + "\n").getBytes("UTF-8"); // 追加换行符
        os.write(data);
        os.flush();
        clientSocket.shutdownOutput();
    } catch (IOException e) {
        Log.e("SocketServer", "连接异常", e);
    }
}
额外注意事项
  • ADB端口转发存在内部缓冲,确保数据可靠传输的关键是明确的消息边界(如换行符、固定长度、自定义协议头),而非依赖Sleep这类不可靠的延迟手段。
  • 始终使用try-with-resources语法管理Socket、流等资源,避免手动关闭遗漏导致的连接泄漏。
  • 若需要传输多条消息,建议定义简单的协议规则(比如每条消息前加长度标识),避免仅靠换行符的局限性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:14:52