解释Relay Server的NAT Punch流程

解读

在国内手游、XR 或数字孪生项目中,“ Relay Server 的 NAT Punch 流程” 是面试官用来快速判断候选人是否真正落地过多人实时联机模块的试金石。
它考察三层能力:

  1. 是否理解国内复杂 NAT 环境(对称型、端口限制型、运营商级 NAT)带来的穿透难点;
  2. 是否能在 Unity 侧用 C# 正确调用底层 Socket,完成候选通道收集、优先级排序、超时重试
  3. 是否能在 Relay 模式下兼顾成本、首包时延、断线重连合规数据出境问题。
    答不出“为什么有了 Relay 还要打洞”或“对称 NAT fallback 策略”,都会被判定为只背过八股文。

知识点

  1. NAT 类型快速判定:Unity 侧通过 STUN RFC 8489 发送 Binding Request,根据 Mapped Address 与 Changed Address 响应差值,把公网拓扑分为完全锥型、IP 受限、端口受限、对称型四类。
  2. 候选通道(Candidate)优先级
    host(局域网)> srflx(公网映射)> relay(TURN 转发)> TURN over TCP(443 逃生通道)。
  3. Relay 与 Punch 的共生关系:Relay 提供100% 可达的 fallback,但流量费用是 P2P 的 3~7 倍,因此必须先尝试 Punch,失败后再 upgrade 到 Relay
  4. 国内网络陷阱
    • 对称 NAT 每次出端口随机,无法预测,必须依赖 Relay;
    • 部分省移动宽带对 UDP 高频端口 30000+ 做 QoS 限速,需要动态端口漂移
    • 微信/QQ 登录环境下,本地防火墙白名单可能只放行 80/443,需要 TURN-TCP 逃生。
  5. Unity 实现细节
    • 使用 Unity.Networking.Transport 或 NGO(Netcode for GameObjects)时,Relay Server 返回的分配 URI 里已包含 SecureKey,C# 侧直接 CreateRelayAllocationAsync 即可,无需自己拼 STUN 包;
    • 若自研,需用 C# Socket 异步发送 20 byte Binding Request,手动解析 XOR-MAPPED-ADDRESS,并在 MonoBehaviour 的 Update 里驱动状态机,避免主线程阻塞。
  6. 性能红线
    • Punch 阶段总时长必须 < 5 s(国内 App Store 审核建议首包 < 3 s);
    • 对称 NAT 场景下,Relay 转发延迟要 < 120 ms(北京到上海电信),否则 FPS 对战体验不可接受。

答案

Relay Server 的 NAT Punch 流程可以拆成**“五步三通道”**,在 Unity 客户端用 C# 完整落地如下:

  1. 收集候选地址
    启动时同时枚举三类 Candidate:

    • host:192.168.x.x 局域网地址;
    • srflx:通过国内公有 STUN(如阿里云、腾讯云边缘节点)获取公网映射;
    • relay:向 Relay Server(通常部署在华东 1/华北 2 合规机房)申请 Allocation,拿到 relay-ip:port 与 256 bit SecureKey。
  2. 优先级排序 & 并发探测
    按 host > srflx > relay 优先级,异步并发发送 UDP Punch 包,但设置差分超时

    • host 500 ms 无回包即放弃;
    • srflx 1.5 s 内重试 3 次,每次端口+1;
    • 若 srflx 失败,立即 upgrade 到 relay,不再等待,保证总时长 < 5 s。
  3. NAT Punch 交换信令
    把本地候选列表通过厂商合规长连接网关(如腾讯 MSDK、阿里 GamingAnywhere)发送给对端,信令走 HTTPS+Protobuffer,避免 UDP 被运营商清洗。

  4. 连通性校验
    对端收到候选后,同样按优先级回包;只要任意一对地址双向可达,即标记为 selected,并停止后续候选探测,减少 30% 流量。

  5. Relay 兜底 & 数据加密
    若双方均为对称 NAT,Punch 必然失败,自动回落到 Relay 转发;此时所有游戏数据经 DTLS 1.2 加密后发送给 Relay,Relay 仅做UDP 对称转发,不解析 Payload,满足国内数据不出境合规要求。

一句话总结:Relay Server 的 NAT Punch 流程=“先尽力打洞,打不通立刻用 Relay 转发,全程 5 s 内完成,且对对称 NAT 有合规兜底”

拓展思考

  1. 如果项目出海东南亚,对称 NAT 比例 < 5%,是否还保留 Relay?
    答:可以降级为纯 P2P+区域 TURN 方案,把 Relay 节点缩到新加坡、孟买两地域,成本下降 40%,但需在 Unity 侧实现动态区域调度断线重选 Relay 逻辑。

  2. 国内小游戏平台(抖音、微信)禁止 UDP,如何改造?
    答:把 Punch 流程改为TURN-TCP over 443,用 Unity 的 WebSocket 模拟 UDP 语义,首包时延会增加 60~80 ms,但可通过帧回滚+客户端预测把感知延迟压到 150 ms 以内。

  3. 2024 年起工信部要求游戏日志留存 6 个月,Relay 侧如何改造?
    答:在 Relay Server 增加透明日志模块,仅记录 5-tuple 与字节数,不存储 Payload,并通过国密 SM4 加密后落盘,既满足审计又避免泄露玩家隐私。