fix(client): 延迟统一用 node.ping(client→数据面 RTT),连接页与节点列表同源一致

撤掉连接页连接态的内核 urltest —— 它与节点列表的 node.ping 是两套口径、两处显示不一致。
统一全部用 node.ping(直接 TCP 握手 节点:443),连接页显示生效节点的 ping、节点列表显示
各节点 ping,永远同一个数。连接态 TUN 测不到新值则保留上次实测(_measure 已改保留)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-29 23:28:39 +08:00
parent 7c7e8e4f6c
commit 0736014552
+3 -14
View File
@@ -2,7 +2,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../bridge/vpn_bridge.dart';
import '../core/responsive/form_factor.dart';
import '../util/format.dart';
import '../l10n/app_text.dart';
@@ -41,12 +40,9 @@ class ConnectPage extends ConsumerWidget {
}
final down = formatSpeed(stats?.downloadSpeed);
final up = formatSpeed(stats?.uploadSpeed);
// 延迟 = client→数据面 RTT,按连接态取不同测法(全局 TUN 下 App socket 测不到真节点):
// · 连接态:内核 urltest —— sing-box 经 REALITY 真实直连数据面探出的 RTT(唯一可靠口径);
// 节点死 → urltest=0 → 落到 —,本身即健康信号。
// · 断开态:节点页 TCP 探针(直接握手 节点:443,无 TUN,真实 RTT)。
var livePing = conn.phase == VpnPhase.on ? _bestUrltest(stats) : node.ping;
if (livePing <= 0 && conn.phase != VpnPhase.on) livePing = node.ping;
// 延迟统一用 node.ping(直接 TCP 握手 节点:443 = client→数据面 RTT),与节点列表同源,
// 两处显示永远一致。连接态全局 TUN 测不到新值 → 保留上次断开态实测(见 nodes_provider._measure)。
final livePing = node.ping;
final pingLabel = livePing > 0 ? '${livePing}ms' : '';
final latencyValue = livePing > 0 ? '$livePing' : '';
@@ -210,13 +206,6 @@ class ConnectPage extends ConsumerWidget {
}
}
/// 内核 urltest 各出站中的最小正延迟(ms);无则 0。连接态用作 client→数据面 RTT。
int _bestUrltest(VpnStatsEvent? s) {
if (s == null) return 0;
final ds = s.urltestResults.where((r) => r.delayMs > 0).map((r) => r.delayMs);
return ds.isEmpty ? 0 : ds.reduce((a, b) => a < b ? a : b);
}
/// 实时速率行(连接成功时显示;来自内核 statsStream 实时数据)。
class _SpeedRow extends StatelessWidget {
const _SpeedRow({required this.t, required this.down, required this.up, required this.latency});