Files

63 KiB
Raw Permalink Blame History

第五部分:客户端开发方案

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.550%以下不扣分)                      │
│     - 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审核相对宽松                                │   │
│  │                                                          │   │
│  │  适用游戏:                                               │   │
│  │  - 手游(全品类)                                         │   │
│  │  - 云游戏                                                 │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘