Flutter使用web_socket_channel对接AWS WebSocket如何保持连接存活
问题根因与解决方案
1. 核心错误:向WebSocketSink传入非法参数
你代码中channel.sink.add({"action": "sendMessage", "data": "test"});直接传入了Map对象,但IOWebSocketChannel的Sink仅支持String类型的JSON序列化字符串或者List<int>类型的二进制数据,传入Map会触发底层WebSocket的隐式异常,直接断开连接且不会触发上层onError回调,这是你出现1006/1005关闭码的主要原因。
修改方案:发送前先对Map做JSON序列化:
import 'dart:convert'; // 替换原来的add调用 channel.sink.add(jsonEncode({"action": "sendMessage", "data": "test"}));
2. 常见隐性问题:Channel实例无长期引用
如果你的IOWebSocketChannel实例是定义在局部方法中的临时变量,方法执行结束后实例会被Dart的垃圾回收机制回收,底层连接会被强制关闭,表现为刚连接就触发onDone。
修改方案:将channel定义为类级别的成员变量,而不是局部变量:
class ChatService { // 类成员变量,持有channel引用避免被GC late IOWebSocketChannel channel; void connect() { // 你的原有连接逻辑 } }
3. 可选优化:等待连接握手完成后再发送消息
IOWebSocketChannel.connect是同步返回,但底层WebSocket的TLS握手、路由鉴权等操作是异步执行的,你可以通过监听channel.ready(web_socket_channel 2.4.0+版本支持)确认连接就绪后再发送消息,避免消息丢失:
// 连接后先等待就绪 await channel.ready; // 再发送消息 channel.sink.add(jsonEncode({"action": "sendMessage", "data": "test"}));
调试兜底方案
如果修改后还有问题,可以用原生WebSocket类替代web_socket_channel做底层测试,直接监听所有状态:
final ws = await WebSocket.connect('wss://my_websocket_endpoint'); ws.listen( (data) => print('收到消息:$data'), onError: (e) => print('连接错误:$e'), onDone: () => print('连接关闭,码:${ws.closeCode}, 原因:${ws.closeReason}'), ); ws.add(jsonEncode({"action": "sendMessage", "data": "test"}));
内容的提问来源于stack exchange,提问作者Tom3652
相关产品推荐
相关产品推荐

