# 第五部分:客户端开发方案 ## 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审核相对宽松 │ │ │ │ │ │ │ │ 适用游戏: │ │ │ │ - 手游(全品类) │ │ │ │ - 云游戏 │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────┘ ```