Dart中for循环阻塞Socket IO emit的问题排查咨询
问题原因与解决方案
你的问题核心在于Dart的单线程事件循环机制:stdin.readLineSync()是同步阻塞调用,会完全占据主线程,导致Socket.IO客户端的网络IO任务(比如emit后的消息发送)无法被事件循环处理,必须等整个for循环执行完毕、主线程空闲后,积压的网络任务才会被处理,所以服务器要等循环结束才收到消息。
修复方案:使用异步读取输入
把同步的readLineSync()替换为异步读取方法,让主线程能及时处理Socket的网络操作,保证消息即时发送。
修改后的client.dart代码(异步循环版本)
import 'dart:io'; import 'package:socket_io_client/socket_io_client.dart' as IO; Future<void> main() async { IO.Socket socket = IO.io('http://localhost:3000', <String, dynamic>{ 'transports': ['websocket'], 'autoConnect': false, }); socket.connect(); for(int a = 0; a < 4; a++){ // 使用异步的readLine(),不阻塞主线程 String? name = await stdin.readLine(); if(name != null && name.trim() == "add"){ socket.emit("msg", "A MESSAGE"); } } socket.disconnect(); }
另一种监听式异步读取版本
import 'dart:io'; import 'dart:convert'; import 'package:socket_io_client/socket_io_client.dart' as IO; void main() { IO.Socket socket = IO.io('http://localhost:3000', <String, dynamic>{ 'transports': ['websocket'], 'autoConnect': false, }); socket.connect(); int inputCount = 0; // 通过监听输入流实现异步读取 stdin.transform(utf8.decoder).listen((rawInput) { String input = rawInput.trim(); if (input == "add") { socket.emit("msg", "A MESSAGE"); } inputCount++; if (inputCount >= 4) { stdin.close(); socket.disconnect(); } }); }
关键说明
- Dart是单线程模型,所有异步任务(包括网络IO、定时器)都依赖事件循环调度。同步阻塞调用会卡住事件循环,导致所有异步任务延迟执行。
stdin.readLine()是异步方法,会立即返回Future,释放主线程,让事件循环可以处理Socket的消息发送操作,因此每次输入"add"后,服务器能立刻收到消息。
内容的提问来源于stack exchange,提问作者asimtot
相关产品推荐
相关产品推荐

