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

Flutter如何通过dart:io实现WebSocket连接 无需使用web_socket_channel包

回答

关于socket_io_client是否可用的说明

  • socket_io_client是Socket.IO协议的专用客户端,仅能对接部署了Socket.IO服务端的接口,无法对接AWS标准WebSocket API。AWS WebSocket API遵循标准RFC 6455 WebSocket协议,和Socket.IO的私有封装协议完全不兼容。
  • 你观察到的它使用HTTP发起连接是Socket.IO本身的握手协商逻辑,即使手动修改协议为wss也无法完成和AWS WebSocket API的正常通信,不建议使用该方案。

使用dart:io原生WebSocket对接AWS WebSocket API实现方案

dart:io内置的WebSocket类是标准WebSocket协议的完整实现,完全支持对接AWS WebSocket API,且支持自定义错误处理、重连逻辑,无需引入第三方依赖。

核心实现步骤

  1. 初始化连接:直接调用WebSocket.connect方法传入AWS WebSocket的wss地址即可,支持自定义请求头(如果AWS接口需要鉴权头可以在这里传入)
  2. 监听消息:通过listen方法监听服务端推送的消息
  3. 错误处理:监听onError、onDone回调处理连接异常、断开场景
  4. 发送消息:调用add方法发送字符串或二进制消息
  5. 关闭连接:调用close方法主动断开连接

完整代码示例

import 'dart:io';
import 'dart:convert';

class AwsWebSocketClient {
  WebSocket? _socket;
  final String wsUrl; // 替换为你的AWS WebSocket API地址
  final Map<String, String>? headers; // 鉴权头等自定义请求头

  AwsWebSocketClient({required this.wsUrl, this.headers});

  // 建立连接
  Future<void> connect() async {
    try {
      _socket = await WebSocket.connect(wsUrl, headers: headers);
      // 心跳间隔,避免AWS主动断开空闲连接,可按需调整
      _socket!.pingInterval = const Duration(seconds: 30);

      // 监听服务端消息
      _socket!.listen(
        (message) {
          // 处理收到的消息,二进制消息可自行调整解析逻辑
          try {
            final data = jsonDecode(message);
            _handleReceiveMessage(data);
          } catch (e) {
            _handleError(e);
          }
        },
        onError: (error) {
          // 连接错误处理
          _handleError(error);
          // 按需触发自动重连
          _reconnect();
        },
        onDone: () {
          // 连接断开处理
          _handleDisconnect(_socket?.closeCode, _socket?.closeReason);
          // 非主动断开场景可触发重连
          if (_socket?.closeCode != 1000) {
            _reconnect();
          }
        },
        cancelOnError: true,
      );
    } catch (e) {
      // 连接建立失败处理
      _handleError(e);
      _reconnect();
    }
  }

  // 发送消息
  void sendMessage(Map<String, dynamic> data) {
    if (_socket?.readyState == WebSocket.open) {
      _socket!.add(jsonEncode(data));
    } else {
      _handleError(Exception('WebSocket未连接,消息发送失败'));
    }
  }

  // 主动关闭连接
  Future<void> disconnect() async {
    await _socket?.close(1000, '主动断开连接');
    _socket = null;
  }

  // 处理收到的消息,按需实现业务逻辑
  void _handleReceiveMessage(dynamic data) {
    print('收到消息: $data');
  }

  // 统一错误处理,按需实现弹窗、日志上报等逻辑
  void _handleError(dynamic error) {
    print('WebSocket异常: $error');
  }

  // 处理连接断开的业务逻辑
  void _handleDisconnect(int? code, String? reason) {
    print('连接断开,code: $code, reason: $reason');
  }

  // 自动重连逻辑,按需调整重试间隔、最大重试次数
  Future<void> _reconnect() async {
    if (_socket?.readyState == WebSocket.open) return;
    await Future.delayed(const Duration(seconds: 5));
    connect();
  }
}

// 使用示例
void main() async {
  final client = AwsWebSocketClient(
    wsUrl: 'wss://你的AWS API ID.execute-api.区域.amazonaws.com/阶段',
    headers: {
      // 若AWS开启IAM鉴权或自定义鉴权,在此传入对应头信息
      'Authorization': '你的鉴权token'
    },
  );
  await client.connect();
  // 发送消息示例,action字段需匹配AWS控制台配置的路由规则
  client.sendMessage({"action": "sendMessage", "data": "测试内容"});
}

注意事项

  • AWS WebSocket API默认要求消息中携带action字段匹配你配置的路由,发送消息时需要按照AWS控制台的配置规则传入对应参数
  • 若使用IAM鉴权,需要提前生成AWS签名放入请求头或者消息参数中,按你自己的鉴权配置调整即可
  • 上述代码的重连逻辑可以根据业务需求调整最大重试次数、退避间隔,避免无限重试消耗资源

内容的提问来源于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:09:00