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
相关产品推荐
相关产品推荐

