1. MMO
ShangCloud
  • ShangCloud简介
  • 立项一周年庆祝
  • v3
    • V3设计理念
    • 扩展使用教程
    • 云变量
      • 接口设计
      • 读取变量
      • 创建或更新变量
      • 删除变量
    • OAuth
      • 获取或刷新 AccessToken
    • MMO联机
      • 说明
    • 娱乐功能
      • 随机图
    • 扩展API
      • QQ消息推送
      • 群推送接口
    • 教程
      • 40code作品绑定教程
      • ZeroCat作品绑定教程
    • 健康监控
      • 平台存活状态
      • MMO 系统状态
      • 平台统计数据
  • v2
    • v2
    • 账号操作
      • 登陆
      • 获取用户信息
      • 绑定40code账户
    • 数据库部分
      • 新建数据库
      • 删除数据库
      • 读取数据库
      • 写入数据库
      • 获取数据库列表
      • 重置数据库
    • 状态获取
      • 服务器总占用
  • v1
    • v1
    • 账号操作
      • 管理员
        • 创建新用户
        • 删除用户
        • 设置管理员
        • 获取用户列表
        • 封禁用户
        • 解封用户
      • 普通用户
        • 登录
        • 更改密码
      • 游客
        • 获取用户状态
        • 注册
    • API部分
      • 获取时间戳
      • 获取版本号
      • 邮件验证码
      • 发送HTTP请求
    • 数据库部分
      • 新建数据库
      • 删除数据库
      • 读取数据库
      • 写入数据库
      • 更改数据库权限
      • 获取数据库列表
    • MySQL接口
    • 服务器状态
      • 获取CPU占用
      • 获取总内存
      • 获取使用中内存
      • 获取指定硬盘总容量
      • 获取指定硬盘使用容量
      • 获取内存占用率
      • 获取指定硬盘占用率
      • 设置风扇转速
      • 设置风扇为手动模式
      • 服务器总状态
  • MMO
    • 接入文档
    • 加入MMO房间
      POST
    • 创建MMO房间
      POST
  • 所有操作
    GET
  • 数据模型
    • Schemas
      • AccessTokenInvalid
      • SuccessResponse
      • BadResponse
      • NoPowerResponse
      • NotFoundResponse
      • ServerErrorResponse
    • 极验数据
    • RoomResult
    • StatusResponse
    • Error
    • MmoStatsResponse
    • PlatformStatsResponse
    • ErrorResponse
  1. MMO

接入文档

本文档描述 TCP 和 UDP 两种客户端接入协议的接入方式、加密方案及消息格式。

目录#

通用加密方案
防重放机制
通用消息类型
TCP 接入
UDP 接入
管理接口

通用加密方案#

两种协议均使用 AES-256-GCM 对称加密,加密载荷格式如下:
+----------+--------------------------------------------------+
| 12B nonce | AES-GCM 密文                                    |
+----------+--------------------------------------------------+
            内部明文结构:
            +----------+-------------------+----------+
            | 8B 时间戳 | 实际消息内容       | 16B tag  |
            +----------+-------------------+----------+
字段长度说明
nonce12 字节每条消息随机生成,不可复用
时间戳8 字节大端序 uint64,发送时刻的 Unix 毫秒时间戳
消息内容可变实际业务数据(明文)
GCM tag16 字节AES-GCM 自动生成的认证标签,含在密文末尾

密钥派生#

TCP 和 UDP 均通过客户端发送的 32 字节密钥种子派生加密密钥:
key = SHA256(seed)  →  32 字节 AES-256 密钥
种子可以是任意 32 字节内容(建议使用随机数或设备指纹的 SHA256)。同一客户端在同一次连接中保持密钥不变。

防重放机制#

服务端维护 20 秒滑动时间窗口:
消息时间戳偏离当前时间超过 20 秒(过去) 或 5 秒(未来) → 拒绝
时间窗口内出现重复 nonce → 拒绝
过期的 nonce 记录自动清理
客户端须保证每条消息使用独立的随机 nonce,且发送时系统时钟误差在 5 秒以内。

通用消息类型#

以下消息类型三种协议通用,以下展示的均为解密后的明文内容。

客户端 → 服务端#

消息内容说明
__hb__心跳包,须在 5 秒内发送一次,超过 10 秒未收到心跳则强制断开
__ping__查询当前房间信息(在线人数 + 成员列表)
{"type":"__join__","uid":"...","nickname":"..."}设置当前用户的 UID 和昵称,加入后广播给房间其他成员
其他任意内容业务消息,广播给房间内所有其他成员

服务端 → 客户端#

消息内容说明
__auth_ok__认证成功确认,收到后方可发送业务消息
__pong__:<人数>:<成员JSON>__ping__ 的响应,示例见下
{"type":"__leave__","uid":"..."}广播通知,某用户已离开房间
__closed__服务端主动关闭连接通知(仅 UDP)
__pong__ 示例:
__pong__:3:[{"uid":"user_1","nickname":"玩家A"},{"uid":"user_2","nickname":"玩家B"},{"uid":"user_3","nickname":"玩家C"}]

TCP 接入#

端口#

由服务端 tcp_port 环境变量配置(默认不启用,需显式配置)。

帧格式#

TCP 是流式协议,使用 4 字节大端序长度前缀分割消息边界:
+--------------------+-------------------------------+
| 4B Length (uint32) | Payload(加密载荷)             |
+--------------------+-------------------------------+
Length:大端序 uint32,表示 Payload 的字节数
Payload:加密载荷,格式见通用加密方案
单帧最大 1,048,576 字节(1 MB)

接入流程#

客户端                                      服务端
  │                                           │
  │──── TCP Connect ────────────────────────► │  ① TCP 三次握手
  │                                           │
  │──── [32B 密钥种子(明文)] ──────────────► │  ② 发送密钥种子
  │                                           │  (服务端派生 AES 密钥)
  │                                           │
  │──── [帧: 加密的 connect_key] ────────────► │  ③ 发送认证帧
  │◄─── [帧: 加密的 "__auth_ok__"] ─────────── │  ④ 认证成功
  │                                           │
  │──── [帧: 加密的 "__hb__"] ───────────────► │  ⑤ 心跳(≤5s 一次)
  │──── [帧: 加密的业务消息] ────────────────► │  ⑥ 发送业务消息
  │◄─── [帧: 加密的广播消息] ─────────────────│  ⑦ 接收房间广播
  │                                           │

步骤说明#

① 建立 TCP 连接
连接服务端 TCP 端口。
② 发送密钥种子
连接建立后,立即发送 32 字节明文种子(无需帧封装,直接写入 TCP 流):
[ 32字节随机种子 ]
服务端接收后执行 SHA256(seed) 派生 AES-256 密钥,后续所有消息均用此密钥加解密。
③ 发送认证帧
使用派生密钥加密 connect_key,封装为帧发送:
connect_key = "从主控分配的用户连接密钥"
frame = encode_frame(encrypt(connect_key))
④ 接收认证结果
收到加密的 __auth_ok__ → 认证成功,进入正常通信
服务端关闭连接 → 认证失败(connect_key 无效或已过期)
⑤⑥⑦ 正常通信
所有消息均用帧格式封装:

UDP 接入#

端口#

由服务端 udp_port 环境变量配置(默认不启用,需显式配置)。

数据包格式#

所有 UDP 数据包均包含 8 字节 ConnectId 前缀:
+--------------------+-------------------------------+
| 8B ConnectId       | Payload(加密载荷)             |
+--------------------+-------------------------------+
ConnectId:大端序 int64
认证包固定为 0
认证成功后使用服务端分配的值
Payload:加密载荷,格式见通用加密方案
UDP 单包最大 65,507 字节

认证包格式(特殊)#

认证包的 Payload 结构与普通数据包不同,包含明文密钥种子:
+--------------------+-------------------+-------------------------------+
| 8B ConnectId = 0   | 32B 密钥种子      | 加密载荷(connect_key)         |
+--------------------+-------------------+-------------------------------+
认证包完整结构:
[0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00] ← ConnectId = 0(8字节)
[32字节明文密钥种子]
[12B nonce][AES-GCM密文(8B时间戳 + connect_key)]

接入流程#

客户端                                      服务端
  │                                           │
  │──── [0 + seed + 加密的 connect_key] ────► │  ① 发送认证包
  │◄─── [connectId + 加密的 "__auth_ok__"] ── │  ② 认证成功(获取 ConnectId)
  │                                           │
  │──── [connectId + 加密的 "__hb__"] ──────► │  ③ 心跳(≤5s 一次)
  │──── [connectId + 加密的业务消息] ────────► │  ④ 发送业务消息
  │◄─── [connectId + 加密的广播消息] ──────── │  ⑤ 接收房间广播
  │                                           │

步骤说明#

① 发送认证包
构造认证包并发送到服务端 UDP 端口:
seed   = random_bytes(32)            // 32字节随机种子
key    = SHA256(seed)                // 派生 AES 密钥(仅本地使用)
packet = [0x00×8] + seed + encrypt(connect_key, key)
udp_send(packet)
② 接收认证响应
response = udp_recv()
connect_id = response[0:8]          // 大端序 int64,后续必须使用此值
plaintext  = decrypt(response[8:], key)
// plaintext == "__auth_ok__"
保存 connect_id,后续所有数据包必须携带此值。
③④⑤ 正常通信
// 发送
packet = connect_id_bytes(8) + encrypt(plaintext, key)
udp_send(packet)

// 接收
packet = udp_recv()
// packet[0:8] 为服务端附加的 connect_id(与自身一致)
plaintext = decrypt(packet[8:], key)

NAT 穿越#

服务端自动跟踪每次收到合法数据包时的来源地址,当客户端 IP 或端口因 NAT 重映射发生变化时,服务端会自动更新会话地址,无需重新认证。

会话超时#

UDP 无连接状态,服务端依赖心跳维持会话:
超过 10 秒未收到 __hb__ → 服务端主动清理会话并触发离线通知
客户端收到 __closed__ 消息 → 会话已被服务端关闭,需重新认证
修改于 2026-04-12 04:30:41
上一页
服务器总状态
下一页
加入MMO房间
Built with