ADB端口转发实现PC与平板Socket通信需Sleep才能正常接收问题
问题原因分析
你的核心问题出在Socket流的读取/写入逻辑不匹配,结合ADB转发的流缓冲特性导致:
- 服务端用
BufferedReader.readLine()读取数据,该方法会一直阻塞,直到读取到换行符\n或者输入流触发EOF(结束信号)。但你客户端发送的JSON字符串没有换行符,也未主动告知服务端写入结束,导致服务端永远卡在读取步骤。 - 添加
Thread.sleep(100)后,客户端最终执行socket.close(),此时服务端输入流触发EOF,readLine()才会返回null并退出循环——这只是靠延迟关闭连接“凑巧”让服务端收到数据,并非正确的通信逻辑。 flush()调用时机错误,应该在写完所有数据后立即执行,而非等到尝试读取回复之后。
解决方案
针对两端代码做以下修正:
客户端(PC)修正
- 在发送的JSON字符串末尾添加换行符
\n,让服务端的readLine()可以识别单条消息结束。 - 写完数据后立即调用
flush(),确保数据立刻推送到服务端。 - 发送完毕后调用
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; // 端口未被占用/服务端未启动 } }
服务端(平板)修正
- 恢复服务端的回复逻辑(若需要给PC回传消息)。
- 回复消息时同样添加换行符,让客户端的
readLine()可以正常识别。 - 使用
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
相关产品推荐
相关产品推荐

