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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:06:01