Socket InputStream读取消息异常,Socket2返回bytesReceived=-1求助
Socket读取返回-1问题分析与解决
核心原因
InputStream.read()返回-1和超时完全是两回事——这说明Socket2的通信对方已经主动关闭了输出流(甚至整个连接),哪怕你觉得连接还活跃,实际对方已经终止了数据发送。
你的代码存在的问题
- 每次调用都重复设置
setSoTimeout(100),完全没必要,建议在Socket初始化时一次性设置好。 - 当
read()返回-1时,直接转字符串会触发StringIndexOutOfBoundsException(因为0到-1的索引范围不合法),而且没做连接断开的判断。 - 循环等待非空字符串的逻辑,会在对方关闭连接时陷入异常,无法正确处理断开场景。
修复后的代码
public String getMessage(int socketNumber) { Socket socket = socketNumber == 2 ? socket2 : socket1; byte[] message = new byte[4096]; int bytesReceived; try { bytesReceived = socket.getInputStream().read(message); // 处理对方关闭连接的情况 if (bytesReceived == -1) { throw new IOException("Socket " + socketNumber + " 已被对方关闭"); } System.out.println("从Socket" + socketNumber + "接收的字节数:" + bytesReceived); return new String(message, 0, bytesReceived); } catch (SocketTimeoutException e) { return ""; } catch (IOException e) { throw new RuntimeException(e); } }
额外注意事项
- 排查Socket2的通信对象:检查你发送给Socket2的消息是否正确,对方是否在响应后主动关闭了输出流,或者对方服务端的逻辑是否存在响应后断开连接的设定。
- 优化循环逻辑:循环调用时,除了判断空字符串,还要处理连接断开的异常,避免无限循环:
String response; try { do { response = getMessage(2); } while (response.isEmpty()); } catch (RuntimeException e) { // 处理Socket2断开的情况,比如重新连接或者终止逻辑 System.err.println("Socket2连接异常:" + e.getMessage()); }
- 统一超时配置:在Socket创建完成后(比如
socket2 = new Socket(host, port)之后)就调用setSoTimeout(100),不用每次读取都重复设置。
内容的提问来源于stack exchange,提问作者Unknown
相关产品推荐
相关产品推荐

