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

Android端OKHttp3 3.10版WebSocket闲置后遇EOFException断开问题咨询

OKHttp3 3.10 WebSocket 闲置后收到101响应抛出EOFException的问题排查与解决

我来帮你梳理这个问题,结合你给出的场景和代码片段,咱们一步步分析:

这属于预期行为吗?

绝对不是预期行为。WebSocket在成功完成101 Switching Protocols协议切换后,理应保持连接直到主动断开、网络故障或双方协商超时。既然iOS端和服务端测试都能正常维持连接,说明问题大概率出在OKHttp 3.10版本的客户端实现上。

可能的原因分析

从你贴出的RealWebSocket.connect()代码片段来看,虽然代码里设置了setSoTimeout(0)(即套接字无读超时),但OKHttp 3.10是2018年的旧版本,存在一些WebSocket相关的稳定性问题:

  • 旧版本的EOF处理逻辑缺陷:这个版本在协议切换后的流读取环节,对闲置连接的异常处理不够完善,当连接闲置一段时间后重新通信时,容易误将正常的101响应后的流状态判定为连接断开,抛出EOFException。
  • Ping/Pong机制的默认配置问题:OKHttp的WebSocket默认会发送Ping帧检测连接活性,但3.10版本的默认间隔可能和服务端的闲置超时策略不匹配,导致连接被误判为失效,进而在后续收到服务端响应时触发异常。
  • 连接池的闲置回收冲突:OKHttp的连接池如果对WebSocket连接的回收逻辑和服务端的保持策略不一致,可能会在连接闲置时主动回收连接,此时再收到服务端的101响应就会触发EOFException。

可行的解决方案

1. 升级OKHttp版本(优先推荐)

这是最直接有效的解决办法。建议升级到3.x系列的最新稳定版(比如3.14.9,是3.x分支的最后一个版本),或者直接迁移到4.x版本。后续版本修复了大量WebSocket相关的bug,包括这类EOFException的误触发场景。

2. 自定义Ping/Pong配置

如果暂时无法升级版本,可以手动设置Ping帧的发送间隔,确保连接始终保持活性,避免被误判为断开:

OkHttpClient client = new OkHttpClient.Builder()
    .pingInterval(30, TimeUnit.SECONDS) // 每30秒发送一次Ping帧
    .build();

3. 校验服务端101响应头

虽然iOS端没问题,但OKHttp 3.10对WebSocket响应头的校验可能更严格。确认服务端返回的101响应包含以下必填头:

  • Upgrade: websocket
  • Connection: Upgrade
  • 正确的Sec-WebSocket-Accept值(需和客户端发送的Sec-WebSocket-Key对应)

4. 自定义异常处理逻辑

在WebSocket的监听中捕获EOFException,判断是否是闲置后的特定场景,然后主动发起重连:

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
    if (t instanceof EOFException && response != null && response.code() == 101) {
        // 针对闲置后收到101时的EOF异常,执行重连逻辑
        reconnectWebSocket();
    } else {
        // 处理其他类型的异常
        handleOtherFailure(t);
    }
}

补充说明

如果升级版本后问题消失,那基本可以确定是旧版本的bug导致的。另外,也可以排查下客户端是否有代理、防火墙等网络组件在闲置后切断连接,但考虑到iOS端正常,这个可能性相对较低。

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

火山引擎 最新活动