Socket.setSoTimeout()未触发问题求助及代码说明
解决Socket setSoTimeout()超时未触发的问题
看起来你遇到的问题是设置了setSoTimeout()但没看到预期的超时效果,我来帮你拆解下原因和解决办法:
问题根源
setSoTimeout(pingTimeOut)的作用是:当调用Socket的读取方法(比如read()、readLine())时,如果在指定时间内没有任何数据可读,就会抛出SocketTimeoutException。但你的代码里存在两个关键问题:
- 未捕获超时异常:你的读取逻辑直接调用
bufferIn.readLine(),没有包裹try-catch块。一旦超时发生,异常会直接终止你的循环甚至整个程序,你自然看不到预期的超时触发逻辑。 - 未处理readLine()返回null的情况:当服务器主动关闭连接时,
readLine()会返回null,如果不处理这个情况,你的循环会因为调用message.isEmpty()而抛出NullPointerException。
修复后的代码示例
把读取逻辑包裹在try-catch中,同时处理返回null的情况:
socket = new Socket(); socket.connect(new InetSocketAddress(ip, port), timeOut); socket.setSoTimeout(pingTimeOut); bufferOut = new PrintWriter(socket.getOutputStream()); bufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8")); socketSubject.onNext(new Pair<>(false,"Connected")); Timber.d("Connected."); while (isRunning){ try { message = bufferIn.readLine(); // 处理服务器关闭连接的情况 if (message == null) { Timber.d("Server closed the connection."); break; } if (!message.isEmpty()){ Timber.d(message); } } catch (SocketTimeoutException e) { // 这里就是超时触发的逻辑 Timber.d("Ping timed out - no response from server"); // 可以在这里执行重连、发送提醒等操作 } catch (IOException e) { // 处理其他IO异常 Timber.e(e, "Error reading from socket"); break; } }
额外注意点
setSoTimeout()只作用于读取操作,对connect()的超时没有影响(你已经用connect()的第二个参数设置了连接超时,这部分是对的)。- 如果你的"ping消息"是需要服务器回复的,记得确保发送ping后,服务器的回复包含换行符(因为你用的是
readLine()),否则即使服务器回复了数据但没有换行,readLine()还是会一直阻塞,直到超时。
内容的提问来源于stack exchange,提问作者John




