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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:12:12