文档

支持

Relay

Relay

Relay 消息协议

Understand how the Relay message protocol transmits data between clients and servers in the Relay service.
阅读时间13 分钟最后更新于 1 个月前

如果您在项目中将 Relay SDK 搭配 UTP 或者搭配 NGO 使用,则支持 Relay 消息协议。不过,如果您使用的是其他引擎或网络解决方案,则需要在使用前实施 Relay 消息协议。请使用 Relay 消息协议规范来实施 Relay 消息协议。 Relay 消息协议要求以“大端序”(也称为“网络序”)表示字段值,即高位先行。 除使用 HMAC 签名的
BIND
消息
外,其他消息均不进行验证。
玩家仅可与属于相同 Unity 项目和环境的其他玩家进行连接并转发消息。Relay 拒绝跨 Unity 环境进行的通信尝试。 所有消息都具有标准标头和消息特定的消息体。请参阅标准标头消息体

消息类型

代码名称描述
0
BIND 消息
BIND
消息表示由客户端发送给 Relay 服务器的绑定请求。
1
BIND_RECEIVED 消息
BIND_RECEIVED
消息表示 Relay 服务器在收到
BIND 请求
后对客户端的成功响应。
2
PING 消息
PING
消息表示客户端和 Relay 服务器之间(双向)发送的 Ping 消息,用于保持连接活动状态。
3
CONNECT_REQUEST 消息
CONNECT_REQUEST
消息表示一个玩家(请求客户端)发送给另一个玩家(目标客户端)的连接请求。
4
预留。
5
预留。
6
ACCEPTED 消息
ACCEPTED
消息表示在请求客户端成功连接到目标客户端后,由 Relay 服务器发送给请求客户端的确认消息。
7
预留。
8
预留。
9
DISCONNECT 消息
DISCONNECT
消息表示两个玩家之间的连接断开请求。
10
RELAY 消息
RELAY
消息表示两个玩家(客户端)之间的消息发送请求。
11
CLOSE 消息
CLOSE
消息表示由客户端发送的从 Relay 服务器解绑的请求。
12
ERROR 消息
ERROR
消息表示发生了错误。

接受模式类型

“接受模式”定义了 Relay 服务器处理客户端连接请求的方式。 Relay 仅支持
AUTO
接受模式。
AUTO
连接模式表示 Relay 服务器在容量允许(即连接数不得超过允许的最大连接数)情况下自动接受连接。
代码名称描述
0
AcceptModeAuto
AcceptModeAuto
表示 Relay 服务器自动接受与客户端的连接。
1
 预留。

标准标头

所有消息类型均使用相同的标准标头,其中包含签名、Relay 消息协议版本以及报文主体中包含的消息。
字节1 ..234
用途
Signature
Version
Type
下表对标准标头中的每个字段进行了介绍。
字段类型描述
Signature
[]byte
Signature
始终为
0xDA72
Version
uint8
Version
是 Relay 消息协议版本。初始版本对应的值为 0
Type
uint8
Type
是表示消息体中所包含消息类型的整数。请参阅消息类型

消息主体

BIND 消息

BIND
消息由客户端发送到 Relay 服务器,用于针对特定分配创建客户端 IP 地址和端口的映射。通过验证该消息可验证客户端的身份。
分配服务收到的响应包含用于验证客户端
BIND
消息所需的信息。分配服务对
BIND
消息的响应即表示当前绑定状态。
在客户端 IP 地址和端口不变的情况下,客户端可发送相同的
BIND
消息。例如,如果客户端 IP 地址或端口发生更改,则当为后续连接发送
BIND
消息时,
Nonce
值必须要大于之前提供的值。
字节1 ..456 ..789 ..NN+1 ..33
用途标头(类型 0)
AcceptMode
Nonce
ConnectionDataLength
ConnectionData
HMAC
下表对
BIND
消息中的每个字段进行了介绍。
字段类型描述
AcceptMode
uint8
AcceptMode
定义了 Relay 服务器针对客户端连接到分配所有者的请求的处理方式。目前仅支持
AUTO
接受模式。请参阅接受模式类型
Nonce
uint16
Nonce
是一次性密码随机数。后续发送的
BIND
消息必须使用递增的随机数值。通常,随机数值从 0 开始。
ConnectionDataLength
uint8
ConnectionDataLength
描述
ConnectionData
的字符长度。允许的最大值为 255
ConnectionData
[]byte
ConnectionData
是<madcap:glossaryterm glossterm="relay-glossary.Term4">发起连接的客户端</madcap:glossaryterm>的加密连接数据。该字段的长度是可变的。最大长度为 255 字节。
HMAC
[32]byte
HMAC
是使用已知密钥和消息中位于前面的字节(包括标头)生成的基于哈希的消息验证代码。请参阅身份验证

安全

必须使用从分配服务返回的密钥对 HMAC 进行签名。如果 HMAC 无效,则 Relay 服务器会静默拒绝
BIND message
Relay 服务器还会验证随机数值,以便缓解攻击者的消息重放攻击。Relay 服务器认定随机数无效,则会静默拒绝。如果客户端第一次使用
BIND message
绑定到 Relay 服务器,随机数值可以是 0

BIND_RECEIVED 消息

Relay 服务器向请求客户端发送
BIND_RECEIVED
消息,用于确认客户端已成功通过
BIND message
绑定到 Relay 服务器。收到确认消息后,请求客户端即可使用
CONNECT_REQUEST message
向目标客户端发起通信。
字节1 ..4
用途标头(类型 1)

PING 消息

PING
消息是简单消息,通过重置客户端超时时间来保持客户端和 Relay 服务器之间的绑定。Relay 服务器会在客户端处于无活动状态 10 秒钟后自动断开与客户端的连接。Relay 服务器收到的关于客户端(作为发送方或接收方)的任何消息均会引发超时时间重置。对于消息收发频率较低的游戏,
PING
消息允许客户端重置断开连接计时器。
每条
PING
消息均包含客户端的分配 ID 和用于标识该消息的任意数字。
Relay 服务器收到来自客户端的
PING
消息后,会将数据包原样发送回客户端。鉴于此,您可以使用
PING
消息检查连接性并测量往返时间。
Relay 服务器在分配 ID 过期的情况下不会发回错误消息。
字节1 ..45 ..2021 ..22
用途标头(类型 2)
AllocationID
Number
下表对
PING
消息中的每个字段进行了介绍。
字段类型描述
AllocationID
[16]byte
AllocationID
是一个 16 字节 UUID,用于标识发送 ping 消息的已分配客户端。
Number
uint16
Number
是 Relay 服务器响应客户端的任意无符号整数,客户端使用该整数将发送和接收的
PING
消息进行关联。

CONNECT_REQUEST 消息

CONNECT_REQUEST
消息由请求客户端发送到 Relay 服务器,用于与目标客户端建立连接。请求客户端希望连接的目标玩家(或目标客户端)由
ToConnectionData
表示,Relay 服务器在对其解密后可以确定要连接的玩家。
字节1 ..45 ..202122 ..
用途标头(类型 3)
AllocationID
ToConnectionData Length
ToConnectionData
下表对
CONNECT_REQUEST
消息中的每个字段进行了介绍。
字段类型描述
AllocationID
[16]byte
AllocationID
是一个 16 字节 UUID,用于标识请求连接的已分配客户端。
ToConnectionDataLength
uint8
ToConnectionDataLength
描述
ToConnectionData
的字符长度。允许的最大值为 255
ToConnectionData
[]byte
ToConnectionData
是描述要连接到的客户端的加密数据块。请参阅连接数据。该字段的长度是可变的。最大长度为 255

ACCEPTED 消息

Relay 服务器会在请求客户端成功连接到目标客户端后,向请求客户端发送一条
ACCEPTED
消息。
字节1 ..45 ..2021 ..36
用途标头(类型 6)
FromAllocationID
ToAllocationID
下表对
ACCEPTED
消息中的每个字段进行了介绍。
字段类型描述
FromAllocationID
[16]byte
FromAllocationID
是一个 16 字节 UUID,用于标识目标客户端。
ToAllocationID
[16]byte
ToAllocationID
是一个 16 字节 UUID,用于标识请求连接的已分配客户端(请求客户端)。

DISCONNECT 消息

DISCONNECT
消息与
CONNECT_REQUEST
握手相反,用于断开一个客户端与其他客户端的连接。客户端可以通过向 Relay 服务器发送
DISCONNECT
消息来断开与其他客户端的连接。
Relay 服务器收到该消息后,会从请求客户端的已连接玩家列表中删除指定的分配 ID,并将
DISCONNECT
请求转发到主机客户端,以便主机客户端更新已连接玩家的地图并删除请求客户端的分配 ID。
之后,Relay 服务器将
DISCONNECT
消息发回客户端进行确认。如果消息主体中的任一分配 ID 无效,Relay 服务器会发送
ERROR message
客户端断开连接后,Relay 服务器会拒绝所有发送至该客户端分配 ID 的
RELAY
消息
。客户端断开连接后,可使用
CONNECT_REQUEST message
重新建立连接。
字节1 ..45 ..2021 ..36
用途标头(类型 9)
FromAllocationID
ToAllocationID
下表对
DISCONNECT
消息中的每个字段进行了介绍。
字段类型描述
FromAllocationID
[16]byte
FromAllocationID
是一个 16 字节 UUID,用于标识请求关闭连接的已分配客户端(请求客户端)。
ToAllocationID
[16]byte
ToAllocationID
是一个 16 字节 UUID,用于标识即将被关闭连接的已分配客户端(目标客户端)。

RELAY 消息

RELAY
消息允许客户端在不知道彼此 IP 地址和端口的情况下,相互发送包含任意字节有效负载的消息。
在客户端之间发送
RELAY
消息之前,Relay 服务器需要确认发送数据包的客户端之前已通过
BIND message
验证为
FromAllocationID
。如果该客户端之前未绑定,Relay 服务器会返回一条
ErrClientPlayerMismatch
ERROR
消息
此外,Relay 服务器还会确认两个客户端之前已通过
CONNECT_REQUEST
交换建立连接。如果两个客户端未进行连接,Relay 服务器会返回一条
ErrNotConnected
ERROR message
如果所有验证均通过,Relay 服务器会将整个消息原样发送到
ToAllocationID
。Relay 服务器不会向
FromAllocationID
发送任何确认消息。
字节1 ..45 ..2021 ..3637 ..3839 ..
用途标头(类型 10)
FromAllocationID
ToAllocationID
Length
Content
下表对
RELAY
消息中的每个字段进行了介绍。
字段类型描述
FromAllocationID
[16]byte
FromAllocationID
是一个 16 字节 UUID,用于标识发送消息的已分配客户端(请求客户端)。
ToAllocationID
[16]byte
ToAllocateID
是一个 16 字节 UUID,用于标识接收消息的已分配客户端(目标客户端)。
Length
uint16
Length
指定了消息内容的长度,以字节为单位。最大长度为 1400
Content
[]byte
Content
包含消息的内容。

CLOSE 消息

CLOSE
消息为幂等消息,允许客户端从 Relay 服务器解绑并取消分配。客户端应在离开游戏会话或关闭游戏客户端时向 Relay 服务器发送
CLOSE
消息。客户端仅可关闭自身与 Relay 服务器的绑定,但无法关闭其他客户端的绑定。
为增加成功发送的机会,客户端应多次发送
CLOSE
消息。由于
CLOSE
消息是幂等的,Relay 服务器在客户端已断开连接的情况下发送
ERROR
消息
不会产生风险。
CLOSE
消息是用于正常终止分配的最佳方式,但并不能保证一定成功。由于可以通过超时时间为客户端取消分配,Relay 服务器不依赖
CLOSE
消息来删除客户端分配。
发送
CLOSE
消息的客户端必须之前通过
BIND
请求
绑定到 Relay 服务器。如果客户端未绑定到 Relay 服务器(或客户端 IP 地址已更改),Relay 服务器会静默拒绝该消息。使用
PING
消息可防止分配意外超时。
字节1 ..45 ..20
用途标头(类型 11)
AllocationID
下表对
CLOSE
消息中的每个字段进行了介绍。
字段类型描述
AllocationID
[16]byte
AllocationID
是一个 16 字节 UUID,用于标识客户端分配。

ERROR 消息

Relay 服务器严格使用
ERROR
消息来通知客户端发生了错误。
字节1 ..45 ..2021
用途标头(类型 12)
AllocationID
ErrorCode
下表对
ERROR
消息中的每个字段进行了介绍。
字段类型描述
AllocationID
[16]byte
AllocationID
是一个 16 字节 UUID,用于标识客户端分配。
ErrorCode
uint8
ErrorCode
表示错误代码。请参阅错误代码

错误代码

下表对 Relay 服务器可能发送到客户端的每个错误消息进行了介绍。
代码名称描述
0
无效协议版本 (
ErrInvalidProtocolVersion
)
当解析后的消息中包含无效的协议版本时,会返回
ErrInvalidProtocolVersion
1
玩家因无活动而超时 (
ErrTimeout
)
当客户端与 Relay 服务器的绑定超时后,会返回
ErrTimeout
。请参阅客户端超时。客户端应使用
PING 消息
来防止产生此错误。
2
未授权 (
ErrUnauthorized
)
当客户端尝试执行未经授权的操作时,会返回
ErrUnauthorized
3
分配 ID 客户端不匹配 (
ErrClientPlayerMismatch
)
客户端使用未知的网络连接向服务器发送
RELAY
消息后,会返回
ErrClientPlayerMismatch
。该消息用于通知客户端其使用的 IP 地址不同于 Relay 服务器上绑定的地址。该错误消息指示客户端应使用新的
BIND 消息
重新进行绑定。
4
未找到分配 ID (
ErrAllocationNotFound
)
当 Relay 服务器无法找到给定分配 ID 对应的分配时,会返回
ErrAllocationNotFound
5
未连接 (
ErrNotConnected
)
当客户端尝试与未连接的客户端通信时,会返回
ErrNotConnected
6
不允许自连接 (
ErrSelfConnectNotAllowed
)
当客户端向具有相同分配 ID 的客户端发送
CONNECT_REQUEST 消息
时,会返回
ErrSelfConnectNotAllowed