Skip to main content
摘要:本文聚焦「网络架构与协议」,梳理核心概念、关键方法与落地实践。
核心理念: 采用 双通道架构。非实时业务 (大厅/养成) 走 HTTP 短连接,实时业务 (战斗/组队) 走 TCP/KCP 长连接。

1. 📡 通信架构 (Communication Channels)

1.1 HTTP 通道 (Lobby & Meta)

  • 适用场景: 登录、商城购买、邮件领取、装备强化、天赋升级。
  • 特点: 无状态、请求-响应模式、易于扩展 (Load Balancer)。
  • 格式: POST /api/v1/{service}/{method}
    • Body: Protobuf 序列化后的二进制流 (为了省流量和防抓包,不直接用 JSON)。

1.2 Socket 通道 (Battle & Social)

  • 适用场景: 实时 PVP、组队副本、聊天、公会战。
  • 协议:
    • TCP: 聊天、状态同步 (对顺序要求高)。
    • KCP (UDP): 战斗位置同步、技能释放 (对延迟敏感,允许少量丢包)。
  • 心跳 (Heartbeat): 每 5 秒 一次,3 次超时断开。

2. 📝 协议设计 (Protocol Design)

我们统一使用 Google Protobuf (v3) 作为序列化标准。

2.1 消息包结构 (Packet Structure)

所有 Socket 消息包遵循以下头部格式:

2.2 Protobuf 定义示例

3. 🔌 API 接口规范 (API Standards)

3.1 幂等性 (Idempotency)

  • 对于扣除资源的操作 (如抽卡、购买),必须支持幂等。
  • 实现: 客户端生成一个 request_uuid,服务器缓存该 ID 的处理结果 5-10 秒。如果收到重复请求,直接返回缓存结果,不重复扣费。

3.2 错误处理

  • 所有回包包含 error_code
  • 通用错误:
    • 1001: Token 过期 (需重新登录)。
    • 1002: 服务器维护中。
    • 2001: 资源不足。

4. 🛡️ 安全性 (Security)

4.1 认证 (Authentication)

  • 登录后获取 SessionToken
  • 后续所有 HTTP 请求 Header 必须携带 Authorization: Bearer {token}
  • Socket 连接建立后的第一个包必须是 AuthPacket

4.2 防重放 (Anti-Replay)

  • 利用包头中的 seq (序列号)。服务器记录该连接处理过的最大 seq,小于等于该值的包直接丢弃。

4.3 数据加密

  • 虽然 Protobuf 本身不可读,但为了防止逆向,关键业务 (登录/支付) 的 Body 层可再加一层 AES-128 加密。密钥在登录握手时通过 RSA 交换。

5. 🔗 网络连接类型 (Network Connection Types)

游戏中不同场景对网络的需求差异巨大,理解各连接类型的特点是架构设计的基础。

5.1 连接类型概览

5.2 Localhost (本地回环)

  • 地址: 127.0.0.1 (IPv4) 或 ::1 (IPv6)
  • 特点:
    • 数据不经过物理网卡,在操作系统内核层面完成。
    • 延迟极低 (<1ms),带宽无限制。
  • 应用场景:
    • 本地开发测试: 程序员单机同时跑 Client 和 Server。
    • 单机游戏存档同步: 使用网络协议作为进程间通信方式。
    • Bot 模拟: 在本地生成大量伪客户端进行压力测试。
  • 注意: 仅用于开发,生产环境禁止暴露 localhost 服务到外网。

5.3 LAN (局域网)

  • 地址范围 (私有地址):
    • 10.0.0.0/8
    • 172.16.0.0/12
    • 192.168.0.0/16
  • 特点:
    • 低延迟 (1-5ms),高带宽。
    • 无 NAT 障碍,设备间可直接互访。
  • 应用场景:
    • 网吧/电竞馆: 局域网对战。
    • 局域网派对: 临时组局,无需外网。
    • 开发联调: 多人同时测试联机功能。
  • 发现机制:
    • 广播 (Broadcast): 发送 UDP 包到 x.x.x.255
    • 组播 (Multicast): 更高效,如 224.0.0.1

5.4 WAN (广域网 / Client-Server 模式)

  • 特点:
    • 服务器需公网 IP: 客户端主动连接。
    • 客户端通常在 NAT 后面,无法被直接访问。
    • 延迟 20-200ms (取决于物理距离和网络质量)。
  • 优点:
    • ✅ 架构简单,客户端只需知道服务器地址。
    • ✅ 服务器权威,作弊难度高。
    • ✅ 天然解决 NAT 穿透问题。
  • 缺点:
    • ❌ 服务器带宽成本高 (所有流量经过)。
    • ❌ 服务器宕机 = 全局不可用。
  • 应用场景: 绝大多数商业网游的默认模式 (MMO、手游)。

5.5 P2P (点对点直连)

  • 原理: 客户端之间直接建立连接,数据不经过中央服务器。
  • NAT 穿透技术:
  • 优点:
    • ✅ 延迟最低 (直连)。
    • ✅ 节省服务器带宽。
  • 缺点:
    • ❌ NAT 穿透复杂,部分环境无法直连。
    • ❌ IP 暴露,存在 DDoS 攻击风险。
    • ❌ 反作弊困难 (无权威服务器)。
  • 应用场景: 格斗游戏、小规模 RTS (如《星际争霸》重制版)。

5.6 Relay Server (中继服务器)

  • 原理: 所有数据经过一个公网服务器中转。
  • 优点:
    • ✅ 100% 连通率 (无视 NAT 类型)。
    • ✅ 可隐藏玩家真实 IP。
    • ✅ 可在服务器层做数据校验/反作弊。
  • 缺点:
    • ❌ 延迟增加 (A→Server→B)。
    • ❌ 服务器带宽成本高。
  • 应用场景:
    • 《Unity Relay Service》、《Photon》等商业方案的后备模式。
    • 隐私敏感场景 (隐藏玩家 IP)。

5.7 混合模式 (推荐)

生产实践: 优先尝试 P2P 直连,失败后自动降级到 Relay。

6. 🔄 同步方式原理与应用 (Synchronization Methods)

网络同步是多人游戏的核心挑战,不同方式各有利弊。

6.1 同步方式对比总览


6.2 帧同步 (Lockstep / Deterministic Simulation)

6.2.1 核心原理

  • 传输内容: 仅传输玩家输入指令 (如: 移动方向、技能 ID),而非游戏状态。
  • 关键要求: 确定性 (Determinism) — 相同输入 + 相同随机种子 = 相同输出。

6.2.2 确定性挑战

6.2.3 时序模型

  • 问题: 任何一人卡顿 = 所有人等待。
  • 优化:
    • 乐观帧 (Optimistic Frame): 先用预测输入执行,错了再回滚。
    • 断线续玩: 超时玩家输入视为”无操作”。

6.2.4 适用场景

  • ✅ RTS (《星际争霸》、《魔兽争霸》)
  • ✅ MOBA (《王者荣耀》)
  • ✅ 格斗游戏 (《街霸》、《GGPO》)
  • ❌ MMO (玩家数量过多,输入同步成本爆炸)

6.3 状态同步 (State Synchronization)

6.3.1 核心原理

  • 传输内容: 服务器定期发送完整/增量游戏状态 (位置、血量、状态等)。
  • 客户端职责: 渲染 + 预测 (可选),不做权威判定

6.3.2 优化策略

6.3.3 优缺点

6.3.4 适用场景

  • ✅ MMO (《魔兽世界》)
  • ✅ 大型多人 FPS (需配合预测)
  • ✅ 实时策略 (非竞技)

6.4 快照插值 (Snapshot Interpolation)

6.4.1 核心原理

  • 核心思想: 客户端故意延后渲染 1-2 个快照,始终在两个已知状态之间插值
  • Buffer Size: 通常 100-200ms (根据网络抖动调整)。

6.4.2 插值计算

Positionrender=PositionS1+(PositionS2PositionS1)×ttS1tS2tS1Position_{render} = Position_{S1} + (Position_{S2} - Position_{S1}) \times \frac{t - t_{S1}}{t_{S2} - t_{S1}}
  • tt 落在 [tS1,tS2][t_{S1}, t_{S2}] 之间时进行线性插值。
  • 高级:使用 Hermite 插值保持速度连续。

6.4.3 优缺点


6.5 客户端预测与服务器回滚 (Client-Side Prediction + Rollback)

6.5.1 核心原理

  1. 客户端预测: 玩家输入后立即在本地执行,不等服务器。
  2. 输入上报: 同时把输入发给服务器。
  3. 服务器确认: 服务器计算权威结果,返回给客户端。
  4. 校正/回滚: 客户端对比预测结果与权威结果,若有误差则回滚并重新模拟

6.5.2 回滚机制 (Rollback Netcode)

  • 关键: 必须保存历史输入历史状态快照

6.5.3 技术要点

6.5.4 适用场景

  • ✅ 格斗游戏 (GGPO 架构)
  • ✅ 高竞技 FPS (《CS2》、《Valorant》)
  • ✅ 动作游戏 (需要即时反馈)

6.6 选型决策树

6.7 实践建议

[!TIP] > 我们的方案 Project Vampirefall 采用:
  • 大厅/养成: HTTP 状态同步 (简单可靠)
  • PVE 战斗: 状态同步 + 快照插值 (容忍延迟,服务器权威)
  • PVP 竞技: 帧同步 + 客户端预测 (低延迟,可回放)
[!WARNING] > 常见陷阱

7. 🎮 单机游戏 vs 联网游戏:关键差异与注意事项

本章目的: 为首次接触联网游戏的程序员提供完整的思维转变指南,也为立项联网游戏提供技术评估清单。

7.1 核心思维差异


7.2 🎲 随机数系统

7.2.1 问题本质

7.2.2 解决方案

7.2.3 代码示例

7.2.4 常见陷阱

[!WARNING] > 随机数陷阱

7.3 ⏱️ 时间与帧率

7.3.1 问题本质

7.3.2 解决方案

7.3.3 代码示例


7.4 🖥️ 浮点数精度

7.4.1 问题本质

浮点运算在不同 CPU/编译器/优化级别下可能产生微小差异
问题: 微小差异会累积,最终导致状态分叉。

7.4.2 解决方案

7.4.3 定点数示例


7.5 🔒 状态管理与权威

7.5.1 单机 vs 联网状态模型

7.5.2 状态分类

7.5.3 设计原则

[!NOTE] > 黄金法则 涉及经济/公平性的数据,必须服务器权威。
  • ✅ 伤害计算在服务器执行
  • ✅ 掉落结果由服务器决定
  • ✅ 技能 CD 由服务器校验
  • ❌ 不要相信客户端上报的”我打死了 BOSS”

7.6 🛡️ 安全与反作弊

7.6.1 威胁模型差异

7.6.2 常见攻击与防御

7.6.3 校验示例


7.7 💾 存档与持久化

7.7.1 差异对比

7.7.2 联网游戏存档策略


7.8 📶 网络异常处理

7.8.1 单机 vs 联网的容错需求

7.8.2 必须处理的网络事件

7.8.3 断线重连流程


7.9 🔄 游戏循环架构

7.9.1 单机 vs 联网游戏循环


7.10 📋 联网游戏立项检查清单

在立项阶段,用此清单评估技术可行性和工作量:

7.10.1 基础设施

  • 服务器部署方案: 云服务商选型 (AWS/阿里云/腾讯云)
  • CDN 与静态资源: 热更新资源分发方案
  • 数据库选型: 关系型 + 缓存层架构
  • 运维监控: 日志收集、报警、性能监控

7.10.2 网络层

  • 协议选择: HTTP/TCP/UDP/KCP
  • 序列化方案: Protobuf/FlatBuffers/MessagePack
  • 加密方案: TLS/自定义加密层
  • NAT 穿透: 是否需要 P2P,备用 Relay

7.10.3 同步方案

  • 同步模式选择: 帧同步/状态同步/混合
  • 确定性需求: 是否需要定点数、确定性物理
  • 延迟补偿: 预测/回滚/插值策略

7.10.4 游戏逻辑

  • 随机数统一: 确定性 PRNG 方案
  • 时间系统: 固定逻辑步长 vs 可变
  • 物理引擎: 是否需要确定性物理

7.10.5 安全与反作弊

  • 权威计算: 关键逻辑放服务器
  • 校验机制: 位移、伤害、资源校验
  • 反外挂策略: 第三方反作弊 SDK?

7.10.6 用户体验

  • 断线重连: 自动重连 + 状态恢复
  • 延迟显示: UI 中展示当前延迟
  • 匹配系统: 地理位置匹配、ELO 等
  • 跨区/跨服: 是否需要支持

7.11 💡 从单机到联网的重构要点

如果你正在将现有单机游戏改造为联网游戏,重点关注以下步骤:

7.11.1 常见重构陷阱

[!NOTE] > 血泪教训

7.12 📚 延伸阅读