hi-client/LATENCY_TEST_LOGIC_CONFIRMATION.md
2025-10-13 18:08:02 +08:00

5.8 KiB
Executable File
Raw Blame History

延迟测试逻辑确认

🎯 需求确认

用户需求:

  • 连接代理时: 保持默认测试规则(使用 SingBox 通过代理测试)
  • 没连接时: 使用本地网络的ping直接连接节点IP

📋 当前实现逻辑

1. 连接状态判断

连接状态变量: kr_isConnected

// 是否已连接
final kr_isConnected = false.obs;

连接状态更新逻辑: _bindConnectionStatus()

void _bindConnectionStatus() {
  ever(KRSingBoxImp.instance.kr_status, (status) {
    switch (status) {
      case SingboxStopped():
        kr_isConnected.value = false;  // 未连接
        break;
      case SingboxStarting():
        kr_isConnected.value = true;   // 连接中
        break;
      case SingboxStarted():
        kr_isConnected.value = true;   // 已连接
        break;
      case SingboxStopping():
        kr_isConnected.value = false;  // 断开中
        break;
    }
  });
}

2. 延迟测试逻辑

主测试方法: kr_urlTest()

Future<void> kr_urlTest() async {
  KRLogUtil.kr_i('📊 当前连接状态: ${kr_isConnected.value}', tag: 'HomeController');
  
  if (kr_isConnected.value) {
    // ✅ 已连接状态:使用 SingBox 通过代理测试(默认测试规则)
    KRLogUtil.kr_i('🔗 已连接状态 - 使用 SingBox 通过代理测试延迟', tag: 'HomeController');
    await KRSingBoxImp.instance.kr_urlTest("select");
    
    // 等待 SingBox 完成测试
    await Future.delayed(const Duration(seconds: 3));
    
    // 检查活动组状态
    final activeGroups = KRSingBoxImp.instance.kr_activeGroups;
    // ... 处理测试结果
  } else {
    // ✅ 未连接状态使用本机网络直接ping节点IP
    KRLogUtil.kr_i('🔌 未连接状态 - 使用本机网络直接ping节点IP测试延迟', tag: 'HomeController');
    KRLogUtil.kr_i('🌐 这将绕过代理,直接使用本机网络连接节点', tag: 'HomeController');
    await _kr_testLatencyWithoutVpn();
  }
}

3. 本机网络测试逻辑

本机网络测试方法: _kr_testLatencyWithoutVpn()

/// 未连接状态下的延迟测试使用本机网络直接ping节点IP
Future<void> _kr_testLatencyWithoutVpn() async {
  KRLogUtil.kr_i('🔌 开始未连接状态延迟测试(使用本机网络)', tag: 'HomeController');
  KRLogUtil.kr_i('🌐 将使用本机网络直接连接节点IP进行延迟测试', tag: 'HomeController');
  
  // 获取所有非auto节点
  final testableNodes = kr_subscribeService.allList
      .where((item) => item.tag != 'auto')
      .toList();
  
  // 并行执行所有测试任务
  final testTasks = testableNodes
      .map((item) => _kr_testSingleNode(item))
      .toList();
  
  await Future.wait(testTasks);
  
  // 统计和显示测试结果
  // ...
}

单个节点测试方法: _kr_testSingleNode()

/// 测试单个节点的延迟使用本机网络直接ping节点IP
Future<void> _kr_testSingleNode(dynamic item) async {
  KRLogUtil.kr_i('🔌 使用本机网络直接连接测试(绕过代理)', tag: 'NodeTest');
  
  // 使用本机网络直接连接测试节点延迟
  final socket = await Socket.connect(
    address,
    port,
    timeout: const Duration(seconds: 8), // 8秒超时
  );
  
  // 获取延迟时间
  final delay = stopwatch.elapsedMilliseconds;
  
  // 设置延迟阈值超过5秒认为节点不可用
  if (delay > 5000) {
    item.urlTestDelay.value = 65535; // 标记为不可用
  } else {
    item.urlTestDelay.value = delay; // 使用本机网络测试的延迟结果
  }
}

逻辑确认

连接代理时kr_isConnected.value = true:

  1. 使用默认测试规则: 调用 KRSingBoxImp.instance.kr_urlTest("select")
  2. 通过代理测试: 使用 SingBox 的 URL 测试功能
  3. 等待测试完成: 等待3秒让 SingBox 完成测试
  4. 获取测试结果: 从 KRSingBoxImp.instance.kr_activeGroups 获取延迟信息

没连接时kr_isConnected.value = false:

  1. 使用本机网络: 调用 _kr_testLatencyWithoutVpn()
  2. 直接连接节点: 使用 Socket.connect() 直接连接节点IP
  3. 绕过代理: 不经过任何代理,使用本机网络
  4. 并行测试: 同时测试所有节点,提高效率
  5. 真实延迟: 获得本机到节点的真实网络延迟

🔍 关键判断点

连接状态判断:

if (kr_isConnected.value) {
  // 连接代理时:使用 SingBox 默认测试规则
} else {
  // 没连接时使用本机网络直接ping节点IP
}

连接状态来源:

  • kr_isConnected 的值来自 KRSingBoxImp.instance.kr_status
  • 当 SingBox 状态为 SingboxStarted()SingboxStarting() 时,kr_isConnected = true
  • 当 SingBox 状态为 SingboxStopped()SingboxStopping() 时,kr_isConnected = false

📊 测试验证

测试场景1: 连接代理时

  • 预期行为: 使用 SingBox 通过代理测试
  • 验证日志: 🔗 已连接状态 - 使用 SingBox 通过代理测试延迟
  • 测试方式: KRSingBoxImp.instance.kr_urlTest("select")

测试场景2: 没连接时

  • 预期行为: 使用本机网络直接ping节点IP
  • 验证日志: 🔌 未连接状态 - 使用本机网络直接ping节点IP测试延迟
  • 测试方式: Socket.connect() 直接连接节点

📝 总结

当前实现完全符合用户需求:

  1. 连接代理时: 保持默认测试规则,使用 SingBox 通过代理测试延迟
  2. 没连接时: 使用本机网络直接ping节点IP绕过代理获取真实延迟

🔧 实现特点:

  • 自动根据连接状态选择测试方式
  • 连接时使用代理测试,未连接时使用直连测试
  • 详细的日志记录,便于调试和验证
  • 并行测试提高效率
  • 完善的错误处理和超时机制

🎯 用户需求已完全实现!