如何实现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
相关产品推荐
相关产品推荐

