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

Dart中如何捕获socket.add()调用抛出的SocketException?

问题原因

你遇到的核心问题是:Socket.add() 仅将数据写入输出缓冲区,不会立即执行网络发送操作,因此连接断开的错误不会在调用 add() 的同步代码块中抛出。该错误会在底层实际发送数据(或尝试刷新缓冲区)时以异步方式触发,或是通过 Socket 的错误流事件抛出,所以你当前的同步 try-catch 无法捕获到它。

而你手动 throw const SocketException("test") 能被捕获,是因为这是同步抛出的异常,完全处于当前代码执行流中。

解决方案

以下是两种可靠的处理方式:

1. 异步刷新缓冲区并捕获异常

修改代码,在 add() 后调用异步方法 flush(),并使用 await 等待其完成,这样就能在 try-catch 中捕获发送失败的异常。注意外层函数需要标记为 async:

if (socket != null) {
  try {
    socket?.add(msg);
    await socket?.flush(); // 等待缓冲区数据发送完成,错误会在此处抛出
  } on SocketException {
    if (kDebugMode) {
      print("Connection closed");
    }
    socket = null;
    // 执行重连或其他清理逻辑
  }
} else {
  if (kDebugMode) {
    print("Socket disconnected");
  }
}

2. 监听 Socket 的错误与关闭事件

Socket 本身是一个 Stream,当连接异常断开或正常关闭时,会触发 onError 或 onDone 事件。通过监听这些事件,可以提前感知连接状态变化,避免后续发送操作触发未处理异常:

// 建立连接后立即监听事件
void setupSocketListeners(Socket socket) {
  socket.listen(
    (data) {
      // 处理接收到的数据
    },
    onError: (error) {
      if (error is SocketException && error.osError?.errorCode == 32) {
        if (kDebugMode) {
          print("Connection closed (broken pipe)");
        }
        this.socket = null;
        // 启动重连逻辑
      }
    },
    onDone: () {
      if (kDebugMode) {
        print("Socket connection closed normally");
      }
      this.socket = null;
      // 启动重连逻辑
    },
    cancelOnError: true, // 出现错误时自动取消监听
  );
}

这种方式能更及时地感知连接状态变化,建议结合第一种方式使用,确保发送操作和连接状态都能被正确处理。

内容的提问来源于stack exchange,提问作者lorenzo-medici

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:32:42