TCP Server客户端主动断开检测及服务端关闭报错问题咨询
Dart TCP Server 连接管理问题解决
一、检测客户端主动断开连接
你代码里client.done.then未触发客户端主动断开的情况,核心原因是client.listen缺少错误与完成回调。当客户端主动断开时,Socket数据流会触发onDone;若为异常断开(如网络中断)则会触发onError,补充这两个回调并配合client.done兜底,就能覆盖所有断开场景:
修改后的监听代码:
client.listen( (data) { String dataString = utf8.decode(data); print(dataString); }, onDone: () { print('客户端主动断开: ${client.remoteAddress.address}:${client.remotePort}'); removeDevice(client); }, onError: (error) { print('客户端异常断开: ${client.remoteAddress.address}:${client.remotePort}, 错误: $error'); removeDevice(client); }, ); // 保留client.done作为兜底,避免极端场景遗漏 client.done.catchError((error) { print('连接回调捕获错误: ${client.remoteAddress.address}:${client.remotePort}, 错误: $error'); }).whenComplete(() { if (connectedDevices.contains(client)) { removeDevice(client); } });
二、服务端关闭时的错误处理与客户端通知
你遇到的错误OS Error: Transport endpoint is not connected, errno = 107翻译为操作系统错误:传输端点未连接,错误码107,原因是connectedDevices列表中存在已断开的Socket,调用close()时触发无效操作错误。
修复方案:
- 遍历客户端列表时用
List.from避免遍历中修改列表的问题 - 关闭Socket前先调用
shutdown(SocketDirection.both),确保客户端能收到断开信号 - 先关闭服务端停止接受新连接,再处理现有客户端
- 捕获关闭操作的异常,避免程序崩溃
修改后的stopServer代码:
void stopServer() async { // 先关闭服务端,停止接受新连接 await server.close(); // 遍历客户端列表(用List.from创建副本,避免原列表修改导致的遍历异常) for (Socket client in List.from(connectedDevices)) { try { // 先关闭读写方向,让客户端感知到断开 client.shutdown(SocketDirection.both); await client.close(); print('已关闭客户端连接: ${client.remoteAddress.address}:${client.remotePort}'); } catch (e) { print('关闭客户端连接失败: ${client.remoteAddress.address}:${client.remotePort}, 错误: $e'); } finally { removeDevice(client); } } setState(() { isConnected = false; }); }
注意:客户端需自行监听自身Socket的onDone或onError事件,才能收到服务端的断开通知,这部分逻辑需要在客户端代码中实现。
内容的提问来源于stack exchange,提问作者Ozgur Saklanmaz
相关产品推荐
相关产品推荐

