import 'dart:collection'; class PacketLossStatistics { static final PacketLossStatistics _instance = PacketLossStatistics._internal(); factory PacketLossStatistics() => _instance; PacketLossStatistics._internal(); // 记录每个messageId的分包信息 // key: messageId, value: {totalPackets, receivedPackets} final Map _packetsMap = HashMap(); // 统计信息 int _totalMessages = 0; // 总消息数 int _lostMessages = 0; // 丢包的消息数 int _totalPackets = 0; // 总分包数 int _lostPackets = 0; // 丢失的分包数 // 记录分包数据 void recordPacket(int messageId, int currentIndex, int totalPackets) { if (!_packetsMap.containsKey(messageId)) { _packetsMap[messageId] = PacketInfo(totalPackets); _totalMessages++; _totalPackets += totalPackets; } _packetsMap[messageId]!.receivedPackets.add(currentIndex); // 如果收到了该messageId的最后一个包,进行统计 if (currentIndex == totalPackets) { _checkPacketLoss(messageId); } } // 检查丢包情况 void _checkPacketLoss(int messageId) { final info = _packetsMap[messageId]!; // 检查是否有丢失的包 int received = info.receivedPackets.length; if (received < info.totalPackets) { _lostMessages++; _lostPackets += (info.totalPackets - received); } // 清理该messageId的记录,避免内存泄漏 _packetsMap.remove(messageId); } // 获取丢包率统计信息 PacketLossInfo getStatistics() { if (_totalMessages == 0 || _totalPackets == 0) { return PacketLossInfo(0.0, 0.0); } // 计算消息级别的丢包率 double messageLossRate = (_lostMessages / _totalMessages) * 100; // 计算分包级别的丢包率 double packetLossRate = (_lostPackets / _totalPackets) * 100; return PacketLossInfo(messageLossRate, packetLossRate); } // 重置统计数据 void reset() { _packetsMap.clear(); _totalMessages = 0; _lostMessages = 0; _totalPackets = 0; _lostPackets = 0; } } // 分包信息类 class PacketInfo { final int totalPackets; final Set receivedPackets = HashSet(); PacketInfo(this.totalPackets); } // 丢包统计信息类 class PacketLossInfo { final double messageLossRate; // 消息丢失率 final double packetLossRate; // 分包丢失率 PacketLossInfo(this.messageLossRate, this.packetLossRate); @override String toString() { return 'Message Loss Rate: ${messageLossRate.toStringAsFixed(2)}%, Packet Loss Rate: ${packetLossRate.toStringAsFixed(2)}%'; } }