服务器列表Ping

📋本页面为参考文档,包含详细的数据与属性说明。

服务器列表Ping(Server List Ping,简称SLP)是Minecraft服务器提供的一项网络接口,客户端通过常规端口查询服务器的MOTD、在线玩家数、最大玩家数以及服务器版本。SLP使用与游戏相同的协议,因此与其他查询方式不同,它默认始终开启。原版客户端就是用这个接口来显示多人游戏服务器列表。1.7版本时SLP协议做了不向后兼容的改动,不过现在的服务器仍然同时支持新老协议。

当前版本(1.7+)

这一版本使用常规的客户端-服务器协议。关于一般数据包格式,请参见协议文档。

握手(Handshake)

客户端先发送一个握手包,将状态设为1。

数据包ID 字段名 字段类型 说明
0x00 协议版本 VarInt 服务器协议版本号。客户端打算用来连接服务器的版本(实际对ping不重要)。如果客户端通过ping来确定该用哪个版本,按约定填-1。
服务器地址 String 主机名或IP,例如 localhost 或 127.0.0.1
服务器端口 Unsigned Short 默认 25565
下一状态 VarInt 应填 1,代表状态(status)

请求(Request)

客户端紧接着发送一个请求包,这个包没有字段。

数据包ID 字段名 字段类型 说明
0x00 无字段

响应(Response)

服务器应返回一个响应包。注意原版服务器会等待后续的Ping包30秒才超时并发送响应。

数据包ID 字段名 字段类型 说明
0x00 JSON响应 String 见下文

JSON响应的格式如下:

{
  "version": {
    "name": "1.8.7",
    "protocol": 47
  },
  "players": {
    "max": 100,
    "online": 5,
    "sample": [
      {"name": "thinkofdeath", "id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"}
    ]
  },
  "description": {
    "text": "Hello world"
  },
  "favicon": "data:image/png;base64,<data>"
}
  • description 是一个聊天组件对象。原版服务器只能提供文本,其中嵌入 § 符号开头的颜色代码。
  • favicon 字段可选。sample 字段必须存在,但可以为空数组。
  • favicon 应为 PNG 图片进行 Base64 编码,并在前面加上 data:image/png;base64,

收到响应包后,客户端可以选择发送下一个包来测延迟,或者如果只需要以上信息,直接断开连接。如果客户端收到格式不正确的响应,会尝试向后兼容的旧版Ping(legacy ping)。

Ping

如果继续,客户端发送一个Ping包,里面包含一个不重要的载荷。

数据包ID 字段名 字段类型 说明
0x01 载荷 Long 可以是任意数字。原版客户端使用系统相关的时间值(毫秒)。

Pong

服务器收到Ping后会回应一个Pong包,然后关闭连接。

数据包ID 字段名 字段类型 说明
0x01 载荷 Long 应与客户端发送的一致

示例

C#、Java、Python、Python3、PHP 等语言的示例代码可在原文档找到。

1.6 版本

1.6使用了一种与Netty重写之前兼容的协议。现代服务器通过起始字节 FE(而非通常的 00)来识别这个协议。

客户端到服务器

客户端连接到服务器标准端口后,不用进行身份验证和登录,而是发送以下数据(十六进制表示):

  • FE — 服务器列表Ping的数据包标识符
  • 01 — 服务器列表Ping的载荷(固定为1)
  • FA — 插件消息的数据包标识符
  • 00 0B — 后面字符串的长度(固定为11,用short表示)
  • 00 4D 00 43 00 7C 00 50 00 69 00 6E 00 67 00 48 00 6F 00 73 00 74 — 字符串 MC|PingHost 的UTF-16BE编码
  • XX XX — 剩余数据的长度(short),计算公式为 7 + len(hostname),其中 len(hostname) 是主机名UTF-16BE编码的字节数
  • XX — 协议版本,例如最后版本的 4a(74)
  • XX XX — 后面字符串的字符数(short)
  • ... — 客户端正在连接的主机名,UTF-16BE编码
  • XX XX XX XX — 客户端正在连接的端口(int)

所有数据类型均为大端序。

数据包示例(十六进制):

0000000: fe01 fa00 0b00 4d00 4300 7c00 5000 6900  ......M.C.|.P.i.
0000010: 6e00 6700 4800 6f00 7300 7400 1949 0009  n.g.H.o.s.t..I..
0000020: 006c 006f 0063 0061 006c 0068 006f 0073  .l.o.c.a.l.h.o.s
0000030: 0074 0000 63dd                           .t..c.

服务器到客户端

服务器用一个0xFF踢人包回复。包以单字节标识符 ff 开始,接着是一个两字节的大端short,表示后面字符串的字符数。实际上可以忽略这个长度,因为服务器发送响应后会关闭连接。

前3个字节之后,数据包是一个UTF-16BE字符串,以两个字符开头:§1,接着是空字符(\0)。实际传输中为 00 a7 00 31 00 00

剩余部分是用空字符(00 00)分隔的字段:

  • 协议版本(例如74)
  • Minecraft服务器版本(例如1.8.7)
  • 服务器MOTD(例如A Minecraft Server)
  • 当前玩家数
  • 最大玩家数

整个包看起来大致如下:

0000000: ff00 2300 a700 3100 0000 3400 3700 0000  ....§.1...4.7...
0000010: 3100 2e00 3400 2e00 3200 0000 4100 2000  1...4...2...A. .
0000020: 4d00 6900 6e00 6500 6300 7200 6100 6600  M.i.n.e.c.r.a.f.
0000030: 7400 2000 5300 6500 7200 7600 6500 7200  t. .S.e.r.v.e.r.
0000040: 0000 3000 0000 3200 30                   ..0...2.0

注意:当使用此协议与1.7.x及更高版本的服务器通信时,响应中的第一个字段(协议版本)总是127,这不是真实的协议号,所以旧客户端会认为该服务器不兼容。

示例

Ruby、PHP等语言的示例代码可参考原文档。

1.4 至 1.5 版本

在1.6之前,客户端到服务器的操作更简单,只发送 FE 01,没有任何后续数据。

示例

PHP、Java、C# 等语言的示例可参考原文档。

Beta 1.8 至 1.3 版本

在1.4之前,客户端只发送 FE

服务器的响应也只包含3个字段,用 § 分隔:

  • 服务器MOTD(例如A Minecraft Server)
  • 当前玩家数
  • 最大玩家数

整个包看起来类似这样:

0000000: ff00 1700 4100 2000 4d00 6900 6e00 6500  ....A. .M.i.n.e.
0000010: 6300 7200 6100 6600 7400 2000 5300 6500  c.r.a.f.t. .S.e.
0000020: 7200 7600 6500 7200 a700 3000 a700 3100  r.v.e.r.§.0.§.1.
0000030: 30                                       0

评论 (0)

暂无评论,快来发表第一条评论吧!

发表评论