import 'dart:io'; import 'dart:async'; import 'kr_log_util.dart'; /// 真正的节点延迟测试工具 class KRLatencyTester { /// TCP 连接测试延迟(真实测试) /// 返回延迟毫秒数,失败返回 65535 static Future testTcpLatency({ required String host, required int port, Duration timeout = const Duration(seconds: 5), }) async { Socket? socket; final stopwatch = Stopwatch(); try { KRLogUtil.kr_i('🔌 开始测试: $host:$port', tag: 'LatencyTester'); stopwatch.start(); // 尝试 TCP 连接 socket = await Socket.connect( host, port, timeout: timeout, ); stopwatch.stop(); final latency = stopwatch.elapsedMilliseconds; KRLogUtil.kr_i('✅ 测试成功: $host:$port - ${latency}ms', tag: 'LatencyTester'); return latency; } on SocketException catch (e) { stopwatch.stop(); KRLogUtil.kr_w('❌ 连接失败: $host:$port - ${e.message}', tag: 'LatencyTester'); return 65535; } on TimeoutException catch (e) { stopwatch.stop(); KRLogUtil.kr_w('⏱️ 连接超时: $host:$port - $e', tag: 'LatencyTester'); return 65535; } catch (e) { stopwatch.stop(); KRLogUtil.kr_e('❌ 测试异常: $host:$port - $e', tag: 'LatencyTester'); return 65535; } finally { // 确保关闭连接 try { await socket?.close(); } catch (e) { // 忽略关闭错误 } } } /// 批量测试多个节点延迟(并发测试) /// 返回 Map<节点tag, 延迟ms> static Future> testMultipleNodes({ required List> nodes, int concurrency = 10, // 并发数 Duration timeout = const Duration(seconds: 5), }) async { final results = {}; final List>> batches = []; // 分批处理 for (int i = 0; i < nodes.length; i += concurrency) { batches.add( nodes.sublist(i, i + concurrency > nodes.length ? nodes.length : i + concurrency) ); } KRLogUtil.kr_i('📊 开始批量测试: ${nodes.length} 个节点,分 ${batches.length} 批,每批 $concurrency 个', tag: 'LatencyTester'); int completedCount = 0; // 逐批测试 for (int batchIndex = 0; batchIndex < batches.length; batchIndex++) { final batch = batches[batchIndex]; KRLogUtil.kr_i('📦 测试第 ${batchIndex + 1}/${batches.length} 批(${batch.length} 个节点)', tag: 'LatencyTester'); // 并发测试当前批次 final futures = batch.map((node) async { final tag = node.key; final address = node.value; final latency = await testTcpLatency( host: address.host, port: address.port, timeout: timeout, ); completedCount++; if (completedCount % 5 == 0 || completedCount == nodes.length) { KRLogUtil.kr_i('📈 测试进度: $completedCount/${nodes.length}', tag: 'LatencyTester'); } return MapEntry(tag, latency); }).toList(); // 等待当前批次完成 final batchResults = await Future.wait(futures); // 收集结果 for (final result in batchResults) { results[result.key] = result.value; } } // 统计结果 final successCount = results.values.where((latency) => latency < 65535).length; final failCount = results.length - successCount; KRLogUtil.kr_i('✅ 批量测试完成', tag: 'LatencyTester'); KRLogUtil.kr_i('📊 成功: $successCount, 失败: $failCount', tag: 'LatencyTester'); // 显示延迟最低的前3个 final successNodes = results.entries .where((e) => e.value < 65535) .toList() ..sort((a, b) => a.value.compareTo(b.value)); if (successNodes.isNotEmpty) { KRLogUtil.kr_i('🏆 延迟最低的前3个节点:', tag: 'LatencyTester'); for (int i = 0; i < 3 && i < successNodes.length; i++) { KRLogUtil.kr_i(' ${i + 1}. ${successNodes[i].key}: ${successNodes[i].value}ms', tag: 'LatencyTester'); } } return results; } } /// 节点地址信息 class SocketAddress { final String host; final int port; SocketAddress(this.host, this.port); @override String toString() => '$host:$port'; }