You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart中WebSocket.readyState始终返回OPEN,如何检测连接断开?

解决Flutter WebSocket无法检测异常断开的问题

我之前在做Flutter WebSocket项目时也踩过这个一模一样的坑!WebSocket的readyState之所以在关闭WiFi后还显示OPEN,核心原因是WebSocket依赖TCP连接,而TCP在网络突然断开时不会立即发送断开通知——只有当TCP尝试发送数据失败并触发超时后,才会更新连接状态,这个过程可能要等好几分钟,完全不符合你的需求。

要准确检测WebSocket是否异常断开,你需要结合以下几种方案:

1. 实现心跳检测机制(最可靠的方案)

这是业界通用的WebSocket异常断开检测方法:客户端定期发送"心跳"消息(或使用WebSocket原生的ping帧),服务器收到后回复"pong"。如果客户端在指定时间内没收到回复,就判定连接已断开。

Flutter中实现原生Ping/Pong心跳

WebSocket? _wsConnection;
Timer? _heartbeatTimeoutTimer;
const int heartbeatInterval = 5; // 每5秒发一次ping
const int heartbeatTimeout = 10; // 10秒没收到pong就判定断开

Future<void> connectToWebSocket() async {
  try {
    _wsConnection = await WebSocket.connect('wss://your-server-url');
    
    // 开启原生ping帧发送
    _wsConnection!.pingInterval = Duration(seconds: heartbeatInterval);
    
    // 监听消息、错误和连接关闭
    _wsConnection!.listen(
      (data) {
        // 处理业务数据
      },
      onError: (error) => _handleConnectionLoss(),
      onDone: () => _handleConnectionLoss(),
    );
    
    // 启动心跳超时检测
    _resetHeartbeatTimeout();
  } catch (e) {
    print('WebSocket连接失败: $e');
  }
}

void _resetHeartbeatTimeout() {
  _heartbeatTimeoutTimer?.cancel();
  _heartbeatTimeoutTimer = Timer(Duration(seconds: heartbeatTimeout), () {
    // 超时未收到pong,主动断开并处理重连
    _handleConnectionLoss();
  });
}

void _handleConnectionLoss() {
  _heartbeatTimeoutTimer?.cancel();
  _wsConnection?.close(WebSocketStatus.goingAway);
  _wsConnection = null;
  
  // 这里可以添加自动重连逻辑
  // reconnectAfterDelay();
}

如果你的服务器不支持自动回复原生pong帧,就改用自定义心跳消息:

// 客户端发送自定义心跳
void _sendHeartbeat() {
  _wsConnection?.add('{"type": "ping"}');
}

// 在listen的data回调中检测pong回复
_wsConnection!.listen(
  (data) {
    final message = jsonDecode(data);
    if (message['type'] == 'pong') {
      _resetHeartbeatTimeout(); // 收到pong就重置超时定时器
    } else {
      // 处理业务数据
    }
  },
  // ... 其他监听逻辑
);

2. 结合设备网络状态监听

你可以借助Flutter的网络状态插件(比如connectivity_plus),当检测到设备完全断网时,主动关闭WebSocket连接,避免readyState的延迟更新。

示例代码

import 'package:connectivity_plus/connectivity_plus.dart';

StreamSubscription<ConnectivityResult>? _connectivitySubscription;

void initConnectivityListener() {
  _connectivitySubscription = Connectivity().onConnectivityChanged.listen((result) {
    if (result == ConnectivityResult.none) {
      // 网络完全断开,主动关闭WebSocket
      _handleConnectionLoss();
    }
  });
}

// 记得在页面销毁时取消订阅
@override
void dispose() {
  _connectivitySubscription?.cancel();
  _heartbeatTimeoutTimer?.cancel();
  _wsConnection?.close();
  super.dispose();
}

总结

不要单纯依赖readyState来判断WebSocket连接状态——它只能检测主动断开或服务器主动关闭的情况。心跳机制是检测异常断开的核心方案,结合网络状态监听可以进一步优化用户体验,确保在网络断开时及时处理连接状态。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:43:37