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

如何判断服务器Socket不可用?Android客户端连接超时优化

Android Socket客户端连接超时优化与服务器可用性判断

一、缩短连接超时至10秒

你当前用new Socket(host, port)直接创建连接的方式,默认超时时间由系统控制(就是你遇到的两分钟),要改成手动指定超时的逻辑才行。Android里可以先创建一个未连接的Socket实例,再调用connect()方法并传入超时时间(单位是毫秒,10秒就是10000毫秒)。

修改后的核心代码如下:

try {
    socketClient = new Socket(); // 先创建未连接的Socket对象
    // 显式设置10秒连接超时
    socketClient.connect(new InetSocketAddress(host, port), 10000);
    
    // 后续的输入输出流初始化逻辑保持不变
    in = socketClient.getInputStream();
    dIn = new DataInputStream(in);
    out = socketClient.getOutputStream();
    dOut = new DataOutputStream(out);
    
    int c = 0;
    String data = "";
    while ((c = dIn.read()) != -1) {
        // 处理读取到的数据
    }
} catch (IOException e) {
    // 10秒内连不上服务器就会触发这里,处理连接失败逻辑
    e.printStackTrace();
    // 关闭相关资源
}

这样修改后,只要10秒内无法和服务器建立连接,就会直接抛出IOException进入catch块,不会再长时间等待。

二、判断服务器Socket是否不可用

判断服务器不可用要分连接阶段连接后两种场景来处理:

1. 连接阶段的判断

在刚才的超时逻辑里,如果connect()抛出异常(比如ConnectExceptionSocketTimeoutException),就说明服务器未启动、网络不通,或者无法在指定时间内建立连接,直接判定服务器不可用即可。

2. 连接建立后的判断

连接成功后,服务器可能主动断开、网络突然中断,这时候可以通过两种方式及时发现:

  • 读取数据的返回值:当服务器主动关闭Socket时,客户端的read()方法会返回-1,此时就能判定连接已断开。
  • 心跳机制+读取超时:如果服务器长时间没有数据发送,单纯靠read()阻塞无法及时感知断开。可以搭配读取超时和心跳包:
    • 先设置读取超时:socketClient.setSoTimeout(5000);(5秒内没读到数据就抛出SocketTimeoutException
    • 开启一个后台线程,每隔一段时间向服务器发送一个极小的心跳数据(比如一个固定字节)
    • 如果发送时抛出异常,或者触发读取超时,就判定服务器不可用

示例代码片段:

// 连接成功后设置读取超时
socketClient.setSoTimeout(5000); // 5秒内没读到数据就触发超时

// 后台心跳线程
new Thread(() -> {
    while (socketClient != null && !socketClient.isClosed()) {
        try {
            // 发送心跳包,比如发送一个字节0
            dOut.write(0);
            dOut.flush();
            Thread.sleep(10000); // 每隔10秒发一次心跳
        } catch (IOException e) {
            // 发送失败,说明服务器已断开
            System.out.println("服务器连接已断开");
            // 关闭连接并处理重连逻辑
            break;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}).start();

// 读取数据的循环修改
try {
    int c = 0;
    String data = "";
    while ((c = dIn.read()) != -1) {
        // 处理读取到的数据
    }
    // 循环退出,说明read返回-1,服务器主动断开
    System.out.println("服务器已主动断开连接");
} catch (SocketTimeoutException e) {
    // 读取超时,服务器无响应或已断开
    System.out.println("服务器无响应,连接可能已断开");
} catch (IOException e) {
    // 其他IO异常,比如连接重置
    System.out.println("服务器连接异常断开");
}

通过这些逻辑就能及时捕捉到服务器Socket的不可用状态了。


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

火山引擎 最新活动