You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Socket.setSoTimeout()未触发问题求助及代码说明

解决Socket setSoTimeout()超时未触发的问题

看起来你遇到的问题是设置了setSoTimeout()但没看到预期的超时效果,我来帮你拆解下原因和解决办法:

问题根源

setSoTimeout(pingTimeOut)的作用是:当调用Socket的读取方法(比如read()readLine())时,如果在指定时间内没有任何数据可读,就会抛出SocketTimeoutException。但你的代码里存在两个关键问题:

  1. 未捕获超时异常:你的读取逻辑直接调用bufferIn.readLine(),没有包裹try-catch块。一旦超时发生,异常会直接终止你的循环甚至整个程序,你自然看不到预期的超时触发逻辑。
  2. 未处理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

火山引擎 最新活动