Dart WebSocket 持续推送场景下指令接收与多客户端连接问题求解
问题根因
1. 服务端无法接收quit指令的原因
Dart 是单线程事件循环模型,你在 WebSocket 连接回调中写了同步阻塞的while循环+同步sleep,直接占满了主线程的执行资源,事件循环完全没有空闲时间去处理webSocket.listen的消息回调,所以客户端发的quit指令永远不会被触发执行,变量q永远不会更新为quit,循环也就不会停止。
2. 仅第一个客户端能收到消息的原因
第一个客户端连接触发回调后,同步while循环直接卡死了整个服务端线程,HttpServer没有机会处理后续新的客户端连接请求,后续客户端的连接请求都会被挂住,自然无法收到推送。另外你把running、q这类连接状态变量定义在main函数全局作用域,所有连接共享变量,即便解决了阻塞问题,多个客户端的状态也会互相覆盖干扰。
修正方案
把同步循环替换为异步周期性定时器,同时把每个连接的状态变量放到连接回调内部,每个连接独立管理自己的运行状态,不共享全局变量:
修正后的服务端代码
import 'dart:io'; import 'dart:async'; main() async { final port = 8080; final webSocketTransformer = WebSocketTransformer(); HttpServer server = await HttpServer.bind(InternetAddress.anyIPv6, port); server.transform(webSocketTransformer).listen((WebSocket webSocket) { print('WebSocket opened.'); // 每个连接独立的状态变量,不共享全局 bool running = true; Timer? pushTimer; webSocket.listen((msg) { print('收到指令:$msg'); if (msg == 'quit') { running = false; pushTimer?.cancel(); webSocket.close(); } else if (msg == 'start' && pushTimer == null) { // 启动异步周期性推送,不会阻塞事件循环 pushTimer = Timer.periodic(const Duration(seconds: 1), (timer) { if (running) { webSocket.add(DateTime.now().toString()); } else { timer.cancel(); } }); } }, onError: (err) { running = false; pushTimer?.cancel(); print(err); }, onDone: () { running = false; pushTimer?.cancel(); print('WebSocket closed.'); }); }); print('Listening on port $port..'); }
可选客户端优化
客户端的sleep也是同步阻塞调用,建议替换为异步等待避免卡住事件循环:
import 'dart:io'; import 'dart:async'; import 'package:web_socket_channel/io.dart'; void main(List<String> arguments) async { final url = 'ws://localhost:8080'; final channel = IOWebSocketChannel.connect(url); channel.sink.add('start'); channel.stream.listen((msg) { print(msg); }); // 替换同步sleep为异步等待 await Future.delayed(const Duration(seconds: 30)); channel.sink.add('quit'); await channel.sink.close(); }
内容的提问来源于stack exchange,提问作者idoz
相关产品推荐
相关产品推荐

