服务器查询协议

服务器查询协议 (SQP) 允许客户端使用 UDP/IP 数据包检索有关正在运行的游戏服务器的信息。

客户端通过向服务器发送 ChallengeRequest 来发起查询。作为响应,服务器发送一个 ChallengeResponse,其中包含 ChallengeId。客户端收到 ChallengeResponse 后,可以继续向服务器查询信息。

以下部分描述了 SQP 的技术规范,包括 数据类型请求类型数据包格式

SQP 支持的游戏服务器状态信息包括

  • 服务器名称:游戏服务器的名称。
  • 构建 ID:游戏服务器正在运行的游戏镜像的标识符。
  • 当前玩家:当前连接的玩家数量。
  • 最大玩家:可以加入游戏服务器的玩家最大数量。
  • IP 地址:游戏服务器所在的机器的 IP 地址。
  • 端口:游戏服务器的端口,客户端可以通过该端口连接到主机上的特定游戏服务器。
  • 游戏类型:游戏服务器正在运行的游戏。
  • 地图:当前在游戏服务器上加载的游戏地图。

Note: SQP works with the Game Server Hosting game server monitoring process to make sure reports by the game server match the information in Game Server Hosting’s database.

要求

在将 SQP 作为游戏服务器查询协议实施之前,您必须使用所有游戏服务器信息填充 ServerInfoData 对象,这在游戏客户端端完成。这确保游戏服务器报告正确的信息。

参考实现

有关 SQP 的示例实现,请参阅 go-svrquery。go-svrquery 是一个使用各种 查询协议(包括 SQP)与游戏服务器通信的 Golang 客户端。

数据类型

所有服务器查询都包含打包成数据流的五种基本数据类型。下表描述了每种类型。所有类型都是大端。

名称描述
byte一个 8 位字符或一个无符号整数。
ushort一个 16 位无符号整数。
uint一个 32 位无符号整数。
ulong一个 64 位无符号整数。
string一个可变长度的字节字段,以 UTF-8 编码,并以包含字符串长度的字节作为前缀。字符串限制为 255 字节。

请求类型

客户端可以向服务器发出五种类型的请求。下表指定了客户端对每种请求类型应该从服务器期望的响应。

请求响应
ChallengeRequest服务器返回一个挑战号,供客户端在查询请求响应中使用。
QueryRequest 包含 ServerInfo服务器返回有关服务器的基本信息,例如当前玩家数量、最大玩家数、游戏类型和构建 ID。

数据包类型

下表包含 SQP 数据包的各种类型。

数据包类型字节值
ChallengeRequest0
ChallengeResponse0
QueryRequest1
QueryResponse1

标头

所有 SQP 数据包(无论是请求还是响应)都包含一个标头,其中包含以下数据。

数据类型评论
类型byte包含数据包类型。请参阅 数据包类型
ChallengeTokenuintChallengeToken 包含挑战号。QueryRequestQueryResponse 数据包类型需要挑战号。请参阅 挑战号
有效负载 包含数据包的主体(如果数据包有主体)。

挑战号

SQP 使用挑战号(一个随机的 32 位整数)来确保发出查询请求的客户端与收到挑战号的客户端相同。

当客户端第一次向服务器发送请求时,服务器会随机选择挑战号并将其包含在数据包标头中。然后,客户端必须在所有后续请求的标头中包含相同的挑战号。

挑战数据包

客户端可以使用挑战数据包检索可用于后续请求的挑战号。

> Note: Challenge packets only have a header. There is no payload.

请求格式

数据评论
标头请参阅 标头

以下代码段包含 ChallengeRequest 数据包的示例

[0x00000000] 0x00 '\0' unsigned char
[0x00000001] 0x00 '\0' unsigned char
[0x00000002] 0x00 '\0' unsigned char
[0x00000003] 0x00 '\0' unsigned char
[0x00000004] 0x00 '\0' unsigned char

响应格式

数据评论
标头请参阅 标头

以下代码段包含 ChallengeResponse 数据包的示例

[0x00000000] 0x00 '\0' unsigned char
[0x00000001] 0x80 '€' unsigned char
[0x00000002] 0x90 '•' unsigned char
[0x00000003] 0x23 '#' unsigned char
[0x00000004] 0x48 'H' unsigned char

查询数据包

客户端可以发送查询数据包来检索有关服务器的信息。游戏服务器托管仅要求游戏服务器使用 ServerInfo 块来响应查询。您可以使用其他请求类型,但它们对于游戏服务器托管来说不是必需的。

块类型

有四种不同的块类型,客户端可以使用查询数据包请求这些块类型。但是,本文档只包含 ServerInfo 块类型,因为它是在游戏服务器托管支持的唯一块类型。

每个块类型的字节值指示请求客户端期望的响应块。当服务器收到查询数据包时,它会检查请求中的 RequestedChunks 字段,并使用块类型的字节值执行按位 AND 操作。如果此操作的结果大于零,则服务器知道已请求块类型。

例如,如果 RequestedChunks&1 > 0,则服务器会使用 ServerInfo 块进行响应。请参阅下面的说明。

> Note: Although there are four types of chunk types available in the SQP protocol, Game Server Hosting only supports the ServerInfo chunk type.

RequestedChunk 示例含义检查
00000001ServerInfoRequestedChunks & 0x01 > 0
00000010保留RequestedChunks & 0x02 > 0
00000100保留RequestedChunks & 0x04 > 0
00000010保留RequestedChunks & 0x08 > 0

说明RequestedChunks 可以同时请求多个块,因此您的实现必须能够对 RequestedChunks 值执行正确的按位检查。

请求格式

所有查询请求的请求格式相同。

> Note: Game Server Hosting only requires a server to respond to ServerInfo requests. Therefore, all other request types are omitted.

数据类型评论
标头 请参阅 标头
版本ushort包含要使用的 SQP 版本。
RequestedChunksbyte包含请求的 ChunkTypes。请参阅 块类型

以下代码段包含 QueryRequest 数据包的示例

[0x00000000] 0x01 '\x1' unsigned char
[0x00000001] 0x80 '€' unsigned char
[0x00000002] 0x31 '1' unsigned char
[0x00000003] 0xbe '¾' unsigned char
[0x00000004] 0x18 '\x18' unsigned char
[0x00000005] 0x00 '\0' unsigned char
[0x00000006] 0x01 '\x1' unsigned char
[0x00000007] 0x01 '\x1' unsigned char

响应格式

所有块类型的前四个字段(VersionCurrentPacketLastPacketPacketLength)共享标准响应格式。数据包中 PacketLength 字段之后的信息根据请求类型而有所不同。

标准响应格式

下表包含所有块类型都相同的响应部分。

数据类型评论
标头 请参阅 标头
版本ushort包含要使用的 SQP 版本。
CurrentPacketbyte不支持。该值应始终为 0。
LastPacketbyte不支持。该值应始终为 0。
PacketLengthushort包含此点之后的数据包长度。

ServerInfo 响应格式

数据类型评论
请参阅 标准响应格式,了解块类型之间不发生变化的字段。
ChunkLengthuint包含此点之后 ServerInfo 块的长度。
CurrentPlayersushort包含服务器上的玩家数量。
MaxPlayersushort包含服务器支持的玩家最大数量。
ServerNamestring包含服务器的名称。
GameTypestring包含服务器上的游戏。
BuildIdstring包含服务器的版本号或构建 ID。
Mapstring包含服务器当前加载的地图。
Portushort包含服务器公开的游戏端口。

以下代码段包含 QueryResponse 数据包的示例

[0x00000000] 0x01 '\x1' unsigned char
[0x00000001] 0xc0 'À' unsigned char
[0x00000002] 0x7a 'z' unsigned char
[0x00000003] 0x6c 'l' unsigned char
[0x00000004] 0x3d '=' unsigned char
[0x00000005] 0x00 '\0' unsigned char
[0x00000006] 0x01 '\x1' unsigned char
[0x00000007] 0x00 '\0' unsigned char
[0x00000008] 0x00 '\0' unsigned char
[0x00000009] 0x00 '\0' unsigned char
[0x0000000a] 0x5b '[' unsigned char
[0x0000000b] 0x00 '\0' unsigned char
[0x0000000c] 0x00 '\0' unsigned char
[0x0000000d] 0x00 '\0' unsigned char
[0x0000000e] 0x57 'W' unsigned char
[0x0000000f] 0x00 '\0' unsigned char
[0x00000010] 0x00 '\0' unsigned char
[0x00000011] 0x00 '\0' unsigned char
[0x00000012] 0x10 '\x10' unsigned char
[0x00000013] 0x14 '\x14' unsigned char
[0x00000014] 0x55 'U' unsigned char
[0x00000015] 0x45 'E' unsigned char
[0x00000016] 0x34 '4' unsigned char
[0x00000017] 0x20 ' ' unsigned char
[0x00000018] 0x44 'D' unsigned char
[0x00000019] 0x65 'e' unsigned char
[0x0000001a] 0x64 'd' unsigned char
[0x0000001b] 0x69 'i' unsigned char
[0x0000001c] 0x63 'c' unsigned char
[0x0000001d] 0x61 'a' unsigned char
[0x0000001e] 0x74 't' unsigned char
[0x0000001f] 0x65 'e' unsigned char
[0x00000020] 0x64 'd' unsigned char
[0x00000021] 0x20 ' ' unsigned char
[0x00000022] 0x53 'S' unsigned char
[0x00000023] 0x65 'e' unsigned char
[0x00000024] 0x72 'r' unsigned char
[0x00000025] 0x76 'v' unsigned char
[0x00000026] 0x65 'e' unsigned char
[0x00000027] 0x72 'r' unsigned char
[0x00000028] 0x2e '.' unsigned char
[0x00000029] 0x2f '/' unsigned char
[0x0000002a] 0x53 'S' unsigned char
[0x0000002b] 0x63 'c' unsigned char
[0x0000002c] 0x72 'r' unsigned char
[0x0000002d] 0x69 'i' unsigned char
[0x0000002e] 0x70 'p' unsigned char
[0x0000002f] 0x74 't' unsigned char
[0x00000030] 0x2f '/' unsigned char
[0x00000031] 0x53 'S' unsigned char
[0x00000032] 0x68 'h' unsigned char
[0x00000033] 0x6f 'o' unsigned char
[0x00000034] 0x6f 'o' unsigned char
[0x00000035] 0x74 't' unsigned char
[0x00000036] 0x65 'e' unsigned char
[0x00000037] 0x72 'r' unsigned char
[0x00000038] 0x47 'G' unsigned char
[0x00000039] 0x61 'a' unsigned char
[0x0000003a] 0x6d 'm' unsigned char
[0x0000003b] 0x65 'e' unsigned char
[0x0000003c] 0x2e '.' unsigned char
[0x0000003d] 0x53 'S' unsigned char
[0x0000003e] 0x68 'h' unsigned char
[0x0000003f] 0x6f 'o' unsigned char
[0x00000040] 0x6f 'o' unsigned char
[0x00000041] 0x74 't' unsigned char
[0x00000042] 0x65 'e' unsigned char
[0x00000043] 0x72 'r' unsigned char
[0x00000044] 0x47 'G' unsigned char
[0x00000045] 0x61 'a' unsigned char
[0x00000046] 0x6d 'm' unsigned char
[0x00000047] 0x65 'e' unsigned char
[0x00000048] 0x5f '_' unsigned char
[0x00000049] 0x54 'T' unsigned char
[0x0000004a] 0x65 'e' unsigned char
[0x0000004b] 0x61 'a' unsigned char
[0x0000004c] 0x6d 'm' unsigned char
[0x0000004d] 0x44 'D' unsigned char
[0x0000004e] 0x65 'e' unsigned char
[0x0000004f] 0x61 'a' unsigned char
[0x00000050] 0x74 't' unsigned char
[0x00000051] 0x68 'h' unsigned char
[0x00000052] 0x4d 'M' unsigned char
[0x00000053] 0x61 'a' unsigned char
[0x00000054] 0x74 't' unsigned char
[0x00000055] 0x63 'c' unsigned char
[0x00000056] 0x68 'h' unsigned char
[0x00000057] 0x03 '\x3' unsigned char
[0x00000058] 0x30 '0' unsigned char
[0x00000059] 0x30 '0' unsigned char
[0x0000005a] 0x31 '1' unsigned char
[0x0000005b] 0x08 '\b' unsigned char
[0x0000005c] 0x48 'H' unsigned char
[0x0000005d] 0x69 'i' unsigned char
[0x0000005e] 0x67 'g' unsigned char
[0x0000005f] 0x68 'h' unsigned char
[0x00000060] 0x72 'r' unsigned char
[0x00000061] 0x69 'i' unsigned char
[0x00000062] 0x73 's' unsigned char
[0x00000063] 0x65 'e' unsigned char
[0x00000064] 0x1e '\x1e' unsigned char
[0x00000065] 0x61 'a' unsigned char