Skip to Content
CrossingNet
协议

协议

大厅与房间之间的二进制控制帧、SETMATCH 的 ACK 语义、JoinToken 的格式与签名,以及一条 trace 怎么跨进程跟住一局。

跨进程的通信只有两处:控制帧(大厅 ⇄ 房间)和票据(大厅 → 客户端 → 房间)。 两者都是明文 TCP,默认假设在内网或本机。

控制帧

[u32 PayloadLength][u8 Type][u32 ReqId][UTF8 Payload]
  • PayloadLength 不含前 4 字节自身,最小为 5
  • Type 见下表
  • ReqId 由发起方生成,接收方按它做幂等缓存:同一个 ReqId 重发不会执行两次
类型值方向用途
Cmd1大厅 → 房间STATUS / STOP / INFO / SETMATCH
CmdAck2房间 → 大厅命令确认,带同一个 ReqId
Hello3房间 → 大厅启动握手
Health4房间 → 大厅健康上报
Event5房间 → 大厅事件推送(DISCONNECT、RECONNECTED 等)
Result6房间 → 大厅结算结果

命令的确认

Cmd 发出后大厅等 CmdAck:

大厅:Cmd(reqId=17, "SETMATCH;instance=…;match=…")
房间:CmdAck(reqId=17, ok)
  • 超时(SetMatchAckTimeoutSeconds,默认 5 秒)重发,最多 SetMatchAckRetryCount(默认 2)次
  • 同 reqId 最多尝试 3 次(协议侧上限),超过就判这条命令失败
  • 文本路径保留:控制通道不通时退回纯文本命令,行为一致但没有 reqId 幂等

SETMATCH 为什么必须等 ACK

SETMATCH 把「这一局是 match X」写进一个已经预热好的房间。如果大厅没确认就登记玩家, 会出现「房间以为自己还是上一局」的错配。所以顺序是:

认领预热实例 → SETMATCH → 等 CmdAck → 登记玩家 → ReserveSlot → 分配

回收后的实例重新可用(InstanceReadyAgain)也走同一条路径。

JoinToken

格式:

<instance>.<player>.<role>.<team>.<expiry>.<sig>
  • instance / player:GUID
  • role:Player / LateJoinPlayer / Spectator / ReconnectPlayer
  • team:队伍号
  • expiry:Unix 秒
  • sig:SHA1(secret|payload) 的十六进制

签名是键控 SHA1,防篡改,不是 HMAC-SHA256;生产可替换。它防的是客户端改票据, 不防抓包——票据是 bearer token,明文 TCP 下拿到就能用。

校验由房间侧做:

FGuid OutInstance, OutPlayer;
ECrossingJoinRole OutRole;
int32 OutTeam;
FString OutError;

CrossingJoinToken::Validate(Secret, Token, ExpectedInstanceId,
    OutInstance, OutPlayer, OutRole, OutTeam, OutError);

票据还会被写进旅行 URL,因此引擎的 LogNet 会打印它;生产上要么关掉相关日志, 要么把票据有效期压短。

trace

每次入队生成一条 trace,跟着这一局一路走:

QueueJoin(生成 trace)
  → ReadyCheck
  → Assign(URL 带 ?CrossingMeta=<trace>)
  → 旅行
  → 房间 Login 写入 PlayerState.CrossingTraceId
  → 房间日志里都带 trace=

排查「这一局为什么没成」时,用 trace 把大厅日志和房间日志拼起来,比 matchId 更早可用 (配对成功前就有 trace)。

版本握手

引擎的 NetworkVersion 与插件的 CROSSINGNET_API_VERSION 绑定:

  • 客户端版本低于房间期望 → 1002 ClientTooOld
  • 版本不一致 → 1001 VersionMismatch

房间启动时把构建版本写进日志(BuildInfo),房间参数里也带 -CrossingBuildVersion, 便于在实例列表里分辨哪个进程是哪次构建。

明文边界

通道加密假设
控制帧(57300)无内网/本机
健康探测(58100+)无内网/本机
旅行与对局引擎默认公网部署自行套隧道/内网

控制帧里带一个 token 字段(CrossingControlAuth::HasValidToken 做精确字段匹配、定长比较), 用于在非隔离网络里拒绝乱发的命令。它不加密内容,只做来源校验。

下一页:匹配。

On this page