+----------+--------------------------------------------------+
| 12B nonce | AES-GCM 密文 |
+----------+--------------------------------------------------+
内部明文结构:
+----------+-------------------+----------+
| 8B 时间戳 | 实际消息内容 | 16B tag |
+----------+-------------------+----------+| 字段 | 长度 | 说明 |
|---|---|---|
| nonce | 12 字节 | 每条消息随机生成,不可复用 |
| 时间戳 | 8 字节 | 大端序 uint64,发送时刻的 Unix 毫秒时间戳 |
| 消息内容 | 可变 | 实际业务数据(明文) |
| GCM tag | 16 字节 | AES-GCM 自动生成的认证标签,含在密文末尾 |
key = SHA256(seed) → 32 字节 AES-256 密钥客户端须保证每条消息使用独立的随机 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_port 环境变量配置(默认不启用,需显式配置)。+--------------------+-------------------------------+
| 4B Length (uint32) | Payload(加密载荷) |
+--------------------+-------------------------------+客户端 服务端
│ │
│──── TCP Connect ────────────────────────► │ ① TCP 三次握手
│ │
│──── [32B 密钥种子(明文)] ──────────────► │ ② 发送密钥种子
│ │ (服务端派生 AES 密钥)
│ │
│──── [帧: 加密的 connect_key] ────────────► │ ③ 发送认证帧
│◄─── [帧: 加密的 "__auth_ok__"] ─────────── │ ④ 认证成功
│ │
│──── [帧: 加密的 "__hb__"] ───────────────► │ ⑤ 心跳(≤5s 一次)
│──── [帧: 加密的业务消息] ────────────────► │ ⑥ 发送业务消息
│◄─── [帧: 加密的广播消息] ─────────────────│ ⑦ 接收房间广播
│ │[ 32字节随机种子 ]SHA256(seed) 派生 AES-256 密钥,后续所有消息均用此密钥加解密。connect_key,封装为帧发送:connect_key = "从主控分配的用户连接密钥"
frame = encode_frame(encrypt(connect_key))__auth_ok__ → 认证成功,进入正常通信udp_port 环境变量配置(默认不启用,需显式配置)。+--------------------+-------------------------------+
| 8B ConnectId | 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 + 加密的广播消息] ──────── │ ⑤ 接收房间广播
│ │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)__hb__ → 服务端主动清理会话并触发离线通知__closed__ 消息 → 会话已被服务端关闭,需重新认证