SA:MP 查询机制
机制概述
SA:MP 查询机制是通过 UDP 数据包传输服务器统计信息的标准协议,可获取服务器名称、玩家延迟、语言设置、在线玩家列表等核心数据。
本文详解该协议工作原理,并指导如何在不依赖官方客户端的情况下实现查询功能。
查询机制
查询是通过 UDP 协议向服务器地址发送的序列化数据包。
您可能会疑惑:"服务器如何区分查询数据包与常规 RakNet 协议数据?" 其原理在于底层 RakNet 套接字层会识别数据包头部的"SAMP"标识(十六进制值:53 41 4D 50),并采用特殊处理流程。查看源码
序列化数据包
传输数据包由以下部分组成:"SAMP" + IP 四元组 + 端口低字节 + 端口高字节 + 操作码
若对 IP 四元组和端口字节的解析方式存在疑问,可参考:IP 地址与端口解析指南
字节长度 | 字段 |
---|---|
4 | "SAMP" |
4 | IP 地址四元组 |
1 | 端口低 8 位 |
1 | 端口高 8 位 |
1 | 操作码 |
操作码说明
各操作码对应不同查询类型:
-
0x69 ('i'):基础信息查询
获取服务器密码状态、在线人数、主机名、游戏模式、语言等核心参数 -
0x72 ('r'):规则查询
返回重力值、天气代码、网站链接等自定义规则参数 -
0x63 ('c'):玩家简表
获取玩家昵称与得分的快速列表 -
0x64 ('d'):玩家详情
包含玩家 ID、昵称、得分、延迟等详细数据 -
0x78 ('x'):RCON 命令
远程控制指令通道(需认证) -
0x70 ('p'):延迟测试
通过四字节随机数计算服务器响应时间
响应数据包
如前述,每个操作码将返回特定格式的响应数据。
所有响应数据包前 11 字节为固定包头(与请求包头完全一致),后续字节为具体响应内容:
i
, r
, c
, d
, p
响应类型数据表
类型 i
响应
字节 | 键值 | 字节宽度 | 描述 |
---|---|---|---|
11 | Password | 1 | 0 表示未设置密码,1 表示已设置密码 |
12-13 | Players | 2 | 当前在线玩家数量 |
14-15 | MaxPlayers | 2 | 服务器最大玩家容量 |
16-19 | (strlen) | 4 | 服务器主机名字符串长度 |
20 + strlen | Hostname | (strlen) | 服务器主机名 |
21-24 | (strlen) | 4 | 游戏模式字符串长度 |
25 + strlen | Gamemode | (strlen) | 服务器游戏模式 |
26-29 | (strlen) | 4 | 服务器语言字符串长度 |
30 + strlen | Language | (strlen) | 服务器使用语言 |
类型 r
响应
字节 | 键值 | 字节宽度 | 描述 |
---|---|---|---|
11-12 | RuleCount | 2 | 服务器提供的规则数量 |
13 | (strlen) | 1 | 规则名称字符串长度 |
14 + strlen | Rulename | (strlen) | 规则名称 |
15 | (strlen) | 1 | 规则值字符串长度 |
16 + strlen | RuleValue | (strlen) | 规则值 |
(从第 13 字节开始循环,共循环 RuleCount 次)
类型 c
响应
字节 | 键值 | 字节宽度 | 描述 |
---|---|---|---|
11-12 | PlayerCount | 2 | 服务器提供的玩家数量 |
13 | (strlen) | 1 | 玩家昵称字符串长度 |
14 + strlen | PlayerNick | (strlen) | 玩家昵称 |
15-18 | Score | 4 | 玩家分数 |
(从第 13 字节开始循环,共循环 PlayerCount 次)
类型 d
响应
字节 | 键值 | 字节宽度 | 描述 |
---|---|---|---|
11-12 | PlayerCount | 2 | 服务器提供的玩家数量 |
13 | PlayerID | 1 | 玩家 ID(取值范围 0-255) |
14 | (strlen) | 1 | 玩家昵称字符串长度 |
15 + strlen | PlayerNick | (strlen) | 玩家昵称 |
16-19 | Score | 4 | 玩家分数 |
20-23 | Ping | 4 | 玩家到服务器的延迟 |
(从第 13 字节开始循环,共循环 PlayerCount 次)
类型 p
响应
字节 | 键值 | 字节宽度 | 描述 |
---|---|---|---|
11 | number 1 | 1 | 客户端发送的伪随机序列第一个数字 |
12 | number 2 | 1 | 伪随机序列第二个数字 |
13 | number 3 | 1 | 伪随机序列第三个数字 |
14 | number 4 | 1 | 伪随机序列第四个数字 |
C 语言实现示例
开源 C 语言库 sampquery-c 实现了完整的查询功能,可作为开发参考:代码仓库