中EN
概念页

UDP 与游戏协议设计

UDP & Game Protocol Design

更新于 2026-10-15 约 4 分钟UDPTCP可靠性拥塞控制序列号AckGaffer

动作游戏的时间关键数据(输入、位姿、物理)只关心最新状态。TCP 的可靠有序流会在丢包时把头阻塞住;正确做法是游戏协议只走 UDP,自己做虚拟连接、按需可靠性与拥塞退避,并按数据类型选择「冗余重发」还是「直接丢弃旧包」。

TCP 为何不适合实时玩法数据

TCP 在 IP 之上伪装成文件流:可靠、有序、带流控。丢失一包就要停下来等重传(常见约 RTT~2×RTT,拥塞退避时更糟),后到的新数据也得排队。FPS 里玩家输入与角色位置过期即废,停等只会冻住画面与操作,随后一坨积压包同一帧涌入。(UDP vs. TCP)

TCP_NODELAY 只能关掉 Nagle 对小包的合并,治不好队头阻塞。

不要把游戏协议拆成 UDP+TCP

TCP 与 UDP 共享 IP 路径,TCP 的拥塞行为可能加剧 UDP 丢包;两边各做一套 NAT/可靠性也更难控。旁路用 HTTP 拉 REST 可以,但玩法协议应完整留在 UDP 上。(UDP vs. TCP)

虚拟连接

在无连接的 UDP 上约定:双方以固定频率互发带 协议 ID 的包即视为在线;服务端可把「第一份合法协议包」当作连上,用 recvfrom 地址过滤;用「多久没收到包」做超时断线。(Virtual Connection over UDP)

序列号、Ack 与 Bitfield

目标不是复刻 TCP,而是:稳定发包,并知道对端收到了哪些包。

包头典型字段:protocol id、sequence、ack、ack bitfield(32 bit)。本地每发一包递增 sequence;对端用 ack + bitfield 冗余确认最近约 33 个序号。从不对同一 sequence 重传;若应用层数据必须再送,装进新序号的新包。约 1 秒未获 ack 可推断丢失(概率判断)。16 位序号要处理回绕比较。(Reliability and Congestion Avoidance over UDP)

sequenceDiagram
  participant A as 端 A
  participant B as 端 B
  A->>B: seq=10 数据
  A->>B: seq=11 数据
  Note over B: 丢了 seq=10
  B->>A: seq=5 ack=11 bitfield含缺口
  Note over A: 知 11 已到、10 可能丢;新数据用 seq=12 发送

上图:丢包不冻结后续包;由应用决定是否用新包补数据。

按数据类型选可靠性

数据类型策略
角色快照 / 最新位姿不可靠;丢了跳到更新的快照(见 快照插值)
很小的帧输入(锁步)每个 UDP 包冗余携带所有未确认输入,直到 ack(见 确定性锁步同步)
可靠事件 / 大块应用层消息 ID + 按需重发;可拆块(Gaffer 后续文)

小输入冗余发送能在「需要可靠有序」的场景下仍击败 TCP,因为不必为单包重传卡住整条流。(Deterministic Lockstep)

简单二进制拥塞控制

测 RTT:发送队列记 (seq, 时间),ack 时取样本,对当前 RTT 做指数平滑(约 10%)。RTT 超阈值(如 250 ms)立刻降到「坏模式」发包率(如 10 pps);持续良好一段时间再回到「好模式」(如 30 pps)。短时间反复跌落则拉长恢复等待,避免震荡。(Reliability and Congestion Avoidance over UDP)目的是避免路由器排队把延迟顶到数秒。

与引擎层的关系

UE 复制与 RPC 建立在引擎网络驱动之上,开发者很少手写 UDP;但「不可靠组播 RPC vs 可靠」「属性复制丢旧取新」的语义,与本页同一套原则一致。见 网络复制与 RPC。

  1. UDP vs. TCP
  2. gafferongames.com/post/udp_vs_tcp
  3. Virtual Connection over UDP
  4. gafferongames.com/post/virtual_connection_over_udp
  5. Reliability and Congestion Avoidance over UDP
  6. gafferongames.com/post/reliability_ordering_and_congestion_avoidance_over_udp
  7. Deterministic Lockstep

相关页面

游戏开发多人网络游戏模型Multiplayer Networking Models多人游戏并不是共享同一份物理现实,而是每位玩家各自看到的近似。历史上主要两条路:对等锁步 (Peer-to-Peer Lockstep)(RTS 仍常用)与权威客户端/服务器 (Authoritative Client/Server)(动作/FPS 主流);后者再叠加客户端预测、插值与延迟补偿,把延迟藏进体验里。游戏开发确定性锁步同步Deterministic Lockstep锁步不同步物体状态,只同步驱动模拟的输入;各方从相同初态用相同固定步长推进。带宽与对象数量无关,但要求比特级确定性,且每人延迟受最慢输入到达时间约束,通常适合约 2–4 人。游戏开发快照插值Snapshot Interpolation发送端按固定频率拍下世界(或相关子集)的快照,接收端不跑权威模拟,而是把渲染时刻拨回一小段,在缓冲里的两份快照之间插值,用额外延迟换平滑,并扛住抖动与偶发丢包。Source 的实体插值与 clinterp 是同一思想的产品化。游戏开发快照压缩与增量编码Snapshot Compression & Delta Encoding提高快照率以降低插值延迟,必须把每快照比特打下来:有界量化、四元数「最小三分量」、静止省略,以及相对对端已确认基线的增量编码。Source 的 delta snapshot 与 ack 跟踪是同一家族的工程实现。游戏开发 · UE5网络复制与 RPCNetwork Replication & RPCUE 采用服务器权威 (Server-Authoritative) 的客户端-服务器模型:游戏真正在服务器上进行,服务器把状态复制 (Replication) 给客户端,客户端通过远程过程调用 (Remote Procedure Call, RPC) 向服务器请求操作。开发者需要显式声明哪些 Actor、属性、函数要走网络,并借助所有权、网络角色、相关性、优先级控制“发给谁、发多少”。UE 5.8 提供通用复制系统、Replication Graph 和实验性的 Iris 三套复制系统。游戏开发 · UE5专用服务器Dedicated ServerUE 多人游戏采用客户端-服务器模型。监听服务器 (listen server) 由某个玩家的客户端兼任服务器;专用服务器 (dedicated server) 无头运行,不渲染画面,也没有本地玩家。专用服务器体积更小、房主没有不公平优势、能专注于玩法逻辑,适合大规模或竞技游戏。构建专用服务器需要源码版引擎和支持客户端-服务器的 C++ 项目,并要有 <ProjectServer.Target.cs。

被这些页面引用3 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原