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

如何实现WebSocket连接后直接发消息并兼容移动端与Web?

兼容移动端与Web端的WebSocket初始化消息解决方案

要实现连接建立后立刻发送初始化消息,同时兼容移动端和Web端,核心是分别适配两端的原生WebSocket实例,再统一包装为web_socket_channel提供的通用通道,具体可通过两种方式实现:

方式一:条件导入分离平台代码(推荐)

这种方式将平台相关的WebSocket创建逻辑拆分到不同文件,代码结构更清晰易维护。

1. 创建平台适配文件

  • 公共接口文件 web_socket_helper.dart
import 'web_socket_helper_io.dart' if (dart.library.html) 'web_socket_helper_web.dart';

abstract class WebSocketHelper {
  static Future<dynamic> connect(String url) => _connect(url);
}
  • 移动端实现 web_socket_helper_io.dart
import 'dart:io';
import 'web_socket_helper.dart';

Future<WebSocket> _connect(String url) {
  return WebSocket.connect(url);
}
  • Web端实现 web_socket_helper_web.dart
import 'dart:html' as html;
import 'dart:async';
import 'web_socket_helper.dart';

Future<html.WebSocket> _connect(String url) {
  final completer = Completer<html.WebSocket>();
  final ws = html.WebSocket(url);
  
  ws.onOpen.listen((_) => completer.complete(ws));
  ws.onError.listen((error) => completer.completeError(error));
  
  return completer.future;
}

2. 业务代码中使用

import 'package:web_socket_channel/web_socket_channel.dart';
import 'web_socket_helper.dart';

WebSocketChannel? _channel;

Future<void> initWebSocket(String wsUrl, String initMessage) async {
  try {
    // 跨平台获取已连接的WebSocket实例
    final ws = await WebSocketHelper.connect(wsUrl);
    
    // 包装为通用WebSocketChannel
    _channel = WebSocketChannel.fromWebSocket(ws);
    
    // 发送服务器要求的初始化消息
    _channel!.sink.add(initMessage);
    
    // 监听服务器返回消息
    _channel!.stream.listen((message) {
      // 处理收到的消息逻辑
    });
  } catch (e) {
    // 处理连接失败异常
    print('WebSocket连接失败: $e');
  }
}

方式二:直接通过kIsWeb判断平台

如果场景简单,也可以在业务代码中直接用kIsWeb区分平台逻辑,无需额外文件:

import 'dart:io' if (dart.library.html) 'dart:html' as html;
import 'package:flutter/foundation.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'dart:async';

WebSocketChannel? _channel;

Future<void> initWebSocket(String wsUrl, String initMessage) async {
  try {
    dynamic ws;
    if (kIsWeb) {
      // Web端需手动监听连接打开事件
      final completer = Completer<html.WebSocket>();
      ws = html.WebSocket(wsUrl);
      ws.onOpen.listen((_) => completer.complete(ws));
      ws.onError.listen((err) => completer.completeError(err));
      ws = await completer.future;
    } else {
      // 移动端直接使用WebSocket.connect获取已连接实例
      ws = await WebSocket.connect(wsUrl);
    }
    
    _channel = WebSocketChannel.fromWebSocket(ws);
    _channel!.sink.add(initMessage);
    
    // 监听消息
    _channel!.stream.listen((message) {
      // 处理消息逻辑
    });
  } catch (e) {
    print('WebSocket连接出错: $e');
  }
}

关键说明

  • Web端的html.WebSocket不会自动等待连接打开再返回实例,必须通过Completer监听onOpen事件,确保发送初始化消息时连接已建立
  • 两种方式最终都通过WebSocketChannel.fromWebSocket将原生实例包装为通用通道,保证后续的消息收发逻辑在移动端和Web端完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:37:14