63 KiB
63 KiB
第五部分:客户端开发方案
5.1 Windows客户端(优先)
5.1.1 网络驱动方案对比
┌──────────────────────────────────────────────────────────────────────────────┐
│ Windows 网络驱动方案对比 │
├──────────────┬──────────────┬──────────────┬──────────────┬─────────────────┤
│ 方案 │ WFP │ WinDivert │ TUN/TAP │ NDIS Filter │
├──────────────┼──────────────┼──────────────┼──────────────┼─────────────────┤
│ 层级 │ 内核态 │ 用户态 │ 用户态 │ 内核态 │
│ 兼容性 │ Win7+ │ Win7+ │ 全平台 │ Win7+ │
│ 性能 │ ★★★★★ │ ★★★★ │ ★★★ │ ★★★★ │
│ 稳定性 │ ★★★★★ │ ★★★★ │ ★★★ │ ★★★ │
│ 进程过滤 │ ✓ │ ✓ │ ✗ │ ✗ │
│ IP/端口过滤 │ ✓ │ ✓ │ ✓ │ ✓ │
│ 协议过滤 │ ✓ │ ✓ │ ✗ │ ✓ │
│ 驱动签名 │ 需要 │ 需要 │ 需要 │ 需要 │
│ 开发难度 │ 高 │ 中 │ 低 │ 高 │
│ 微软官方 │ ✓ │ ✗(第三方) │ ✗ │ ✓ │
│ 蓝屏风险 │ 低 │ 低 │ 无 │ 中 │
├──────────────┼──────────────┼──────────────┼──────────────┼─────────────────┤
│ 推荐度 │ ★★★★★ │ ★★★★ │ ★★★ │ ★★★ │
├──────────────┴──────────────┴──────────────┴──────────────┴─────────────────┤
│ │
│ ★ 推荐方案:WFP (Windows Filtering Platform) │
│ │
│ 理由: │
│ 1. 微软官方支持,Win7-Win11全系列 │
│ 2. 内核态过滤,性能最优 │
│ 3. 支持按进程PID过滤(核心需求) │
│ 4. 支持ALE层(应用层强制)和传输层过滤 │
│ 5. 稳定性最高,蓝屏风险最低 │
│ 6. 支持Win10/11的Modern Standby │
│ │
│ 备选方案:WinDivert(开发阶段快速原型验证) │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
5.1.2 WFP驱动架构详细设计
┌──────────────────────────────────────────────────────────────────┐
│ WFP Callout Driver 架构 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 用户态 (Ring 3) │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ Accelerator Client Process │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │
│ │ │ │ 流量管理 │ │ 隧道引擎 │ │ 策略引擎 │ │ │ │
│ │ │ │ Engine │ │ Tunnel │ │ Policy │ │ │ │
│ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │
│ │ │ └──────────────┴──────────────┘ │ │ │
│ │ │ │ │ │ │
│ │ │ DeviceIoControl │ │ │
│ │ │ │ │ │ │
│ │ │ ┌──────────────────────────────────────────┐ │ │ │
│ │ │ │ WFP Control Interface │ │ │ │
│ │ │ │ - 添加/删除过滤规则 │ │ │ │
│ │ │ │ - 获取流量统计 │ │ │ │
│ │ │ │ - 配置驱动参数 │ │ │ │
│ │ │ └──────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 内核态 (Ring 0) │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ WFP Callout Driver (.sys) │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ ALE Layer (Application Layer Enforcement) │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ ALE_AUTH_CONNECT_V4 │ │ │ │ │
│ │ │ │ │ - 拦截出站连接请求 │ │ │ │ │
│ │ │ │ │ - 获取进程PID、目标IP、端口 │ │ │ │ │
│ │ │ │ │ - 查询策略:是否需要加速 │ │ │ │ │
│ │ │ │ │ - 决定:放行(FWP_ACTION_PERMIT) │ │ │ │ │
│ │ │ │ │ 拦截(FWP_ACTION_BLOCK) │ │ │ │ │
│ │ │ │ │ 重定向(修改目标地址) │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ ALE_AUTH_RECV_ACCEPT_V4 │ │ │ │ │
│ │ │ │ │ - 拦截入站连接请求 │ │ │ │ │
│ │ │ │ │ - 用于P2P游戏场景 │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ Transport Layer │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ OUTBOUND_TRANSPORT_V4 │ │ │ │ │
│ │ │ │ │ - 出站数据包级别过滤 │ │ │ │ │
│ │ │ │ │ - 修改目标地址(重定向到隧道) │ │ │ │ │
│ │ │ │ │ - 添加标记用于回程识别 │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ INBOUND_TRANSPORT_V4 │ │ │ │ │
│ │ │ │ │ - 入站数据包过滤 │ │ │ │ │
│ │ │ │ │ - 识别隧道回程包并还原 │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ Network Layer │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ IP_PACKET_V4 │ │ │ │ │
│ │ │ │ │ - 数据包级别统计 │ │ │ │ │
│ │ │ │ │ - 流量计数 │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ 数据结构 │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ FilterRule { │ │ │ │ │
│ │ │ │ │ ProcessId uint32 │ │ │ │ │
│ │ │ │ │ DestIP net.IP │ │ │ │ │
│ │ │ │ │ DestPort uint16 │ │ │ │ │
│ │ │ │ │ Protocol uint8 // TCP/UDP │ │ │ │ │
│ │ │ │ │ Action uint8 // Permit/Block │ │ │ │ │
│ │ │ │ │ TunnelType uint8 // UDP/QUIC │ │ │ │ │
│ │ │ │ │ NodeID string // 目标节点 │ │ │ │ │
│ │ │ │ │ } │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
5.1.3 游戏流量识别
┌──────────────────────────────────────────────────────────────────┐
│ 游戏流量识别方案 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 识别维度: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. 进程识别(最可靠) │ │
│ │ - 获取进程PID │ │
│ │ - 查询进程路径 │ │
│ │ - 匹配游戏配置库 │ │
│ │ 示例: │ │
│ │ PID=1234 → C:\Genshin Impact\GenshinImpact.exe │ │
│ │ → 匹配为"原神" │ │
│ │ │ │
│ │ 2. IP识别(精准) │ │
│ │ - 维护游戏服务器IP列表 │ │
│ │ - 查询目标IP是否属于某游戏 │ │
│ │ 示例: │ │
│ │ 目标IP=47.245.x.x → 属于"原神亚服" │ │
│ │ │ │
│ │ 3. 域名识别(灵活) │ │
│ │ - DNS请求拦截 │ │
│ │ - 查询域名是否属于某游戏 │ │
│ │ 示例: │ │
│ │ 域名=*.mihoyo.com → 属于"原神" │ │
│ │ │ │
│ │ 4. 端口识别(辅助) │ │
│ │ - 特定端口通常对应特定游戏 │ │
│ │ 示例: │ │
│ │ 端口27015-27030 → 可能是Steam游戏 │ │
│ │ │ │
│ │ 5. 协议特征识别(深度包检测) │ │
│ │ - 分析数据包载荷特征 │ │
│ │ - 匹配已知游戏协议 │ │
│ │ 示例: │ │
│ │ 前4字节=0x01020304 → "某某游戏"协议头 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 识别优先级:进程 > IP > 域名 > 端口 > 协议特征 │
│ │
│ 游戏配置数据库结构: │
│ │
│ // GameConfig 游戏配置 │
│ { │
│ "game_id": "genshin_impact", │
│ "name": "原神", │
│ "icon": "genshin.png", │
│ "category": "mmorpg", │
│ "process_names": [ │
│ "GenshinImpact.exe", │
│ "YuanShen.exe" │
│ ], │
│ "install_paths": [ │
│ "C:\\Program Files\\Genshin Impact\\", │
│ "D:\\Games\\Genshin Impact\\" │
│ ], │
│ "servers": [ │
│ { │
│ "name": "亚服", │
│ "region": "asia", │
│ "ip_ranges": [ │
│ "47.245.0.0/16", │
│ "8.219.0.0/16" │
│ ], │
│ "domains": [ │
│ "*.mihoyo.com", │
│ "*.hoyoverse.com" │
│ ], │
│ "ports": [443, 80, 22102], │
│ "protocol": "tcp+udp" │
│ }, │
│ { │
│ "name": "美服", │
│ "region": "america", │
│ "ip_ranges": ["47.252.0.0/16"], │
│ "ports": [443, 80, 22102], │
│ "protocol": "tcp+udp" │
│ } │
│ ], │
│ "capture_mode": "process_ip", │
│ "tunnel_mode": "udp_relay", │
│ "priority": "high", │
│ "qos_class": "realtime" │
│ } │
│ │
│ // ServerConfig 服务器配置 │
│ { │
│ "server_id": "asia_01", │
│ "game_id": "genshin_impact", │
│ "name": "亚服-东京", │
│ "ip": "47.245.1.1", │
│ "port": 22102, │
│ "protocol": "udp", │
│ "location": {"lat": 35.6762, "lng": 139.6503}, │
│ "isp": "softbank" │
│ } │
│ │
│ // RouteConfig 路由配置 │
│ { │
│ "route_id": "genshin_asia_route_01", │
│ "game_id": "genshin_impact", │
│ "source_region": "china_north", │
│ "dest_region": "japan", │
│ "access_node": "cn-bj-01", │
│ "relay_nodes": ["cn-sh-01", "hk-01"], │
│ "exit_node": "jp-tokyo-01", │
│ "protocol": "quic", │
│ "fec_level": 2, │
│ "priority": "high" │
│ } │
│ │
└──────────────────────────────────────────────────────────────────┘
5.2 自动选路系统
5.2.1 测速算法
┌──────────────────────────────────────────────────────────────────┐
│ 测速算法详细设计 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 1. 延迟测试(RTT) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 算法:UDP Ping │ │
│ │ │ │
│ │ 输入:目标节点IP、端口 │ │
│ │ 输出:RTT(毫秒) │ │
│ │ │ │
│ │ 步骤: │ │
│ │ 1. 发送UDP探测包(带时间戳) │ │
│ │ 2. 等待回复 │ │
│ │ 3. 计算 RTT = 收到时间 - 发送时间 │ │
│ │ 4. 连续发送10个包,间隔100ms │ │
│ │ 5. 去除最高和最低值,取平均 │ │
│ │ │ │
│ │ 伪代码: │ │
│ │ func measureRTT(node string) float64 { │ │
│ │ var rtts []float64 │ │
│ │ for i := 0; i < 10; i++ { │ │
│ │ start := time.Now() │ │
│ │ sendUDPPing(node) │ │
│ │ waitPong() │ │
│ │ rtt := time.Since(start).Milliseconds() │ │
│ │ rtts = append(rtts, float64(rtt)) │ │
│ │ time.Sleep(100 * time.Millisecond) │ │
│ │ } │ │
│ │ sort.Float64s(rtts) │ │
│ │ // 去除最高最低,取平均 │ │
│ │ return average(rtts[1:9]) │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 2. 丢包率测试 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 算法:统计法 │ │
│ │ │ │
│ │ 步骤: │ │
│ │ 1. 发送20个UDP包,间隔50ms │ │
│ │ 2. 等待2秒收集回复 │ │
│ │ 3. 统计收到的回复数 │ │
│ │ 4. 丢包率 = (20 - 回复数) / 20 │ │
│ │ 5. 重复3轮,取平均 │ │
│ │ │ │
│ │ 伪代码: │ │
│ │ func measureLoss(node string) float64 { │ │
│ │ var losses []float64 │ │
│ │ for round := 0; round < 3; round++ { │ │
│ │ sent := 20 │ │
│ │ received := 0 │ │
│ │ for i := 0; i < sent; i++ { │ │
│ │ sendUDPPing(node) │ │
│ │ time.Sleep(50 * time.Millisecond) │ │
│ │ } │ │
│ │ // 收集回复 │ │
│ │ timeout := time.After(2 * time.Second) │ │
│ │ for { │ │
│ │ select { │ │
│ │ case <-pongChan: │ │
│ │ received++ │ │
│ │ case <-timeout: │ │
│ │ goto done │ │
│ │ } │ │
│ │ } │ │
│ │ done: │ │
│ │ loss := float64(sent-received) / float64(sent) │ │
│ │ losses = append(losses, loss) │ │
│ │ } │ │
│ │ return average(losses) │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 3. 抖动测试(Jitter) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 算法:RTT标准差 │ │
│ │ │ │
│ │ 公式:Jitter = sqrt(Σ(RTTi - RTT_avg)² / N) │ │
│ │ │ │
│ │ 步骤: │ │
│ │ 1. 使用RTT测试的10个样本 │ │
│ │ 2. 计算平均值 │ │
│ │ 3. 计算每个样本与平均值的差的平方和 │ │
│ │ 4. 开方得到标准差 │ │
│ │ │ │
│ │ 伪代码: │ │
│ │ func measureJitter(rtts []float64) float64 { │ │
│ │ avg := average(rtts) │ │
│ │ var sum float64 │ │
│ │ for _, rtt := range rtts { │ │
│ │ diff := rtt - avg │ │
│ │ sum += diff * diff │ │
│ │ } │ │
│ │ return math.Sqrt(sum / float64(len(rtts))) │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 4. 带宽测试 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 算法:递增探测法 │ │
│ │ │ │
│ │ 步骤: │ │
│ │ 1. 发送递增大小的数据包:1KB, 4KB, 16KB, 64KB, 256KB │ │
│ │ 2. 测量每个大小的传输时间 │ │
│ │ 3. 计算吞吐量 = 大小 / 时间 │ │
│ │ 4. 取最大吞吐量作为带宽估计 │ │
│ │ │ │
│ │ 伪代码: │ │
│ │ func measureBandwidth(node string) float64 { │ │
│ │ sizes := []int{1024, 4096, 16384, 65536, 262144} │ │
│ │ var maxBw float64 │ │
│ │ for _, size := range sizes { │ │
│ │ data := make([]byte, size) │ │
│ │ start := time.Now() │ │
│ │ sendData(node, data) │ │
│ │ waitACK() │ │
│ │ elapsed := time.Since(start).Seconds() │ │
│ │ bw := float64(size) * 8 / elapsed / 1e6 │ │
│ │ if bw > maxBw { │ │
│ │ maxBw = bw │ │
│ │ } │ │
│ │ } │ │
│ │ return maxBw // Mbps │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
5.2.2 评分算法
┌──────────────────────────────────────────────────────────────────┐
│ 节点评分算法 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 综合评分公式: │
│ │
│ Score(i) = 100 │
│ - RTT_penalty(i) │
│ - Loss_penalty(i) │
│ - Jitter_penalty(i) │
│ - Load_penalty(i) │
│ + Bonus(i) │
│ │
│ 各项扣分计算: │
│ │
│ 1. RTT扣分: │
│ RTT_penalty = max(0, (RTT - RTT_base) × RTT_factor) │
│ 其中: │
│ - RTT_base = 30ms(基准延迟) │
│ - RTT_factor = 0.5(每ms扣0.5分) │
│ - 最大扣分:50分 │
│ │
│ 2. 丢包扣分: │
│ Loss_penalty = Loss_rate × Loss_factor │
│ 其中: │
│ - Loss_rate = 丢包率(0-1) │
│ - Loss_factor = 200(每1%丢包扣2分) │
│ - 最大扣分:50分 │
│ │
│ 3. 抖动扣分: │
│ Jitter_penalty = Jitter × Jitter_factor │
│ 其中: │
│ - Jitter = 抖动值(ms) │
│ - Jitter_factor = 2(每ms抖动扣2分) │
│ - 最大扣分:30分 │
│ │
│ 4. 负载扣分: │
│ Load_penalty = (Load_rate - Load_threshold) × Load_factor │
│ 其中: │
│ - Load_rate = 负载率(0-1) │
│ - Load_threshold = 0.5(50%以下不扣分) │
│ - Load_factor = 40 │
│ - 最大扣分:20分 │
│ │
│ 5. 加分项: │
│ - 专线节点:+10分 │
│ - BGP多线:+5分 │
│ - 同ISP:+5分 │
│ - 同城市:+10分 │
│ │
│ 评分等级: │
│ ┌──────────┬──────────┬──────────────────────────┐ │
│ │ 分数 │ 等级 │ 说明 │ │
│ ├──────────┼──────────┼──────────────────────────┤ │
│ │ 90-100 │ 极佳 │ 最优选择,绿色显示 │ │
│ │ 70-89 │ 良好 │ 推荐选择,黄色显示 │ │
│ │ 50-69 │ 一般 │ 可用,橙色显示 │ │
│ │ <50 │ 较差 │ 不推荐,红色显示 │ │
│ └──────────┴──────────┴──────────────────────────┘ │
│ │
│ 伪代码实现: │
│ │
│ func calculateScore(node *Node, user *User) float64 { │
│ score := 100.0 │
│ │
│ // RTT扣分 │
│ rttPenalty := math.Max(0, (node.RTT-30)*0.5) │
│ rttPenalty = math.Min(rttPenalty, 50) │
│ score -= rttPenalty │
│ │
│ // 丢包扣分 │
│ lossPenalty := node.LossRate * 200 │
│ lossPenalty = math.Min(lossPenalty, 50) │
│ score -= lossPenalty │
│ │
│ // 抖动扣分 │
│ jitterPenalty := node.Jitter * 2 │
│ jitterPenalty = math.Min(jitterPenalty, 30) │
│ score -= jitterPenalty │
│ │
│ // 负载扣分 │
│ if node.LoadRate > 0.5 { │
│ loadPenalty := (node.LoadRate - 0.5) * 40 │
│ score -= loadPenalty │
│ } │
│ │
│ // 加分项 │
│ if node.IsDedicatedLine { score += 10 } │
│ if node.IsBGP { score += 5 } │
│ if node.ISP == user.ISP { score += 5 } │
│ if node.City == user.City { score += 10 } │
│ │
│ return math.Max(0, math.Min(100, score)) │
│ } │
│ │
└──────────────────────────────────────────────────────────────────┘
5.2.3 节点选择算法
┌──────────────────────────────────────────────────────────────────┐
│ 节点选择算法 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 输入: │
│ - 用户信息:地理位置、ISP、当前网络状况 │
│ - 游戏信息:目标服务器地址、协议类型 │
│ - 节点列表:所有可用节点及其状态 │
│ │
│ 输出: │
│ - 最优节点(主节点) │
│ - 备用节点列表(2-3个) │
│ - 推荐路由路径 │
│ │
│ 算法流程: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Step 1: 候选节点筛选 │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ for each node in all_nodes: │ │ │
│ │ │ if node.status != "online": │ │ │
│ │ │ skip │ │ │
│ │ │ if node.load_rate > 0.9: │ │ │
│ │ │ skip │ │ │
│ │ │ if not node.supports_game(game_id): │ │ │
│ │ │ skip │ │ │
│ │ │ candidates.add(node) │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Step 2: 地理位置匹配 │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ // 优先选择同区域节点 │ │ │
│ │ │ same_region = filter(candidates, same_region) │ │ │
│ │ │ if len(same_region) > 0: │ │ │
│ │ │ candidates = same_region │ │ │
│ │ │ │ │ │
│ │ │ // 优先选择同ISP节点 │ │ │
│ │ │ same_isp = filter(candidates, same_isp) │ │ │
│ │ │ if len(same_isp) > 0: │ │ │
│ │ │ candidates = same_isp │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Step 3: 质量评分 │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ for each node in candidates: │ │ │
│ │ │ node.score = calculateScore(node, user) │ │ │
│ │ │ │ │ │
│ │ │ // 按评分排序 │ │ │
│ │ │ candidates.sort_by_score_desc() │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Step 4: 选择最优 │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ best_node = candidates[0] │ │ │
│ │ │ backup_nodes = candidates[1:3] // 取2个备用 │ │ │
│ │ │ │ │ │
│ │ │ // 构建路由路径 │ │ │
│ │ │ route = build_route(user, best_node, game_server) │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
5.2.4 自动切换算法
┌──────────────────────────────────────────────────────────────────┐
│ 自动切换算法 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 切换触发条件(满足任一即触发): │
│ 1. 当前节点RTT > 最优节点RTT × 1.5 │
│ 2. 当前节点丢包率 > 5% │
│ 3. 连续3次探测质量下降 │
│ 4. 当前节点负载 > 80% │
│ 5. 当前节点离线 │
│ 6. 用户手动切换 │
│ │
│ 切换决策流程: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 每隔10秒执行一次检测: │ │
│ │ │ │
│ │ func autoSwitchCheck() { │ │
│ │ // 1. 测试当前节点质量 │ │
│ │ currentQuality = testNode(currentNode) │ │
│ │ │ │
│ │ // 2. 测试备用节点质量 │ │
│ │ for each backup in backupNodes: │ │
│ │ backup.quality = testNode(backup) │ │
│ │ │ │
│ │ // 3. 找到最优节点 │ │
│ │ bestBackup = findBest(backupNodes) │ │
│ │ │ │
│ │ // 4. 判断是否需要切换 │ │
│ │ needSwitch := false │ │
│ │ │ │
│ │ // 条件1:延迟差异 │ │
│ │ if currentQuality.RTT > bestBackup.RTT * 1.5 { │ │
│ │ needSwitch = true │ │
│ │ } │ │
│ │ │ │
│ │ // 条件2:丢包率 │ │
│ │ if currentQuality.LossRate > 0.05 { │ │
│ │ needSwitch = true │ │
│ │ } │ │
│ │ │ │
│ │ // 条件3:连续下降 │ │
│ │ if qualityDeclineCount >= 3 { │ │
│ │ needSwitch = true │ │
│ │ qualityDeclineCount = 0 │ │
│ │ } │ │
│ │ │ │
│ │ // 条件4:负载过高 │ │
│ │ if currentNode.LoadRate > 0.8 { │ │
│ │ needSwitch = true │ │
│ │ } │ │
│ │ │ │
│ │ // 5. 执行切换 │ │
│ │ if needSwitch && bestBackup.Score > 60 { │ │
│ │ switchTo(bestBackup) │ │
│ │ } │ │
│ │ } │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 切换执行流程(无缝切换): │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ func switchTo(newNode *Node) { │ │
│ │ // 1. 预建立新连接 │ │
│ │ newConn = establishConnection(newNode) │ │
│ │ │ │
│ │ // 2. 迁移会话状态 │ │
│ │ migrateSession(currentSession, newConn) │ │
│ │ │ │
│ │ // 3. 切换流量 │ │
│ │ redirectTraffic(newConn) │ │
│ │ │ │
│ │ // 4. 验证新连接 │ │
│ │ if verifyConnection(newConn) { │ │
│ │ // 5. 关闭旧连接 │ │
│ │ closeConnection(oldConn) │ │
│ │ currentNode = newNode │ │
│ │ log("Switch success") │ │
│ │ } else { │ │
│ │ // 切换失败,回滚 │ │
│ │ rollback(oldConn) │ │
│ │ log("Switch failed, rolled back") │ │
│ │ } │ │
│ │ } │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
5.3 macOS/iOS/Android客户端
┌──────────────────────────────────────────────────────────────────┐
│ 跨平台客户端方案 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ macOS客户端: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 技术栈:Swift + Network Extension (NEPacketTunnelProvider)│ │
│ │ │ │
│ │ 流量捕获: │ │
│ │ - Network Extension (NEPacketTunnelProvider) │ │
│ │ - 系统级VPN框架,稳定性高 │ │
│ │ - 支持按App过滤(macOS 11+) │ │
│ │ │ │
│ │ 隧道实现: │ │
│ │ - 用户态UDP隧道 │ │
│ │ - 或QUIC隧道(quic-go Swift binding) │ │
│ │ │ │
│ │ 限制: │ │
│ │ - 需要App Store审核 │ │
│ │ - Network Extension有沙箱限制 │ │
│ │ - 无法实现内核态驱动 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ iOS客户端: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 技术栈:Swift + Network Extension │ │
│ │ │ │
│ │ 流量捕获: │ │
│ │ - NEPacketTunnelProvider (Packet Tunnel) │ │
│ │ - 支持按App过滤(iOS 14+) │ │
│ │ - 系统级VPN框架 │ │
│ │ │ │
│ │ 限制: │ │
│ │ - App Store审核严格(需说明加速器用途) │ │
│ │ - 沙箱限制更严格 │ │
│ │ - 后台运行限制 │ │
│ │ - 无法实现内核态操作 │ │
│ │ │ │
│ │ 适用游戏: │ │
│ │ - 手游(原神、PUBG Mobile等) │ │
│ │ - 云游戏 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ Android客户端: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 技术栈:Kotlin + VpnService │ │
│ │ │ │
│ │ 流量捕获: │ │
│ │ - VpnService (系统级VPN) │ │
│ │ - 支持TUN设备 │ │
│ │ - 可获取进程UID │ │
│ │ │ │
│ │ 优势: │ │
│ │ - 开发灵活度最高 │ │
│ │ - 可获取进程信息 │ │
│ │ - 支持自定义协议 │ │
│ │ - Google Play审核相对宽松 │ │
│ │ │ │
│ │ 适用游戏: │ │
│ │ - 手游(全品类) │ │
│ │ - 云游戏 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘