Minecraft Server TCP 状态获取详解
测试版本为1.20.6,插件服务器,理论上适用于1.7+版本服务器,已知forge服务器在测试延迟时会出现未收到 Server response的情况
开源Minecraft Server Status已在Github发布,项目地址:https://github.com/GoodBoyboy666/Minecraft-Server-Status
数据包结构
在wiki.vg上我们可以看到,Minecraft数据包的格式如下图:
整个数据包格式采用数据包长度
+Packet ID
+数据
的格式。
数据包长度
和Packet ID
均使用VarInt
数据类型,具体可以看 varint是啥你真的知道么?
这里的数据包长度
仅包含Packet ID
+数据
的长度,不包含数据包长度
自身的长度。
握手
TCP三次握手不再赘述,这里主要讲与Minecraft Server之间的握手
从上图中可以看出HandShake包的大致结构:Packet ID
+Protocol Version
+Server Address
+Server Port
+Next state
。
HandShake包的ID为0x00
,Protocol Version
具体可以参考Protocol version numbers,Server Address
与Server Port
则为服务器地址和端口,Next state
为下一步状态,1
为获取状态,2
为登录。
因此参考wiki后理论上
整个完整的HandShake包结构为:
VarInt类型的Pakect Length
+Packet ID
+VarInt类型的Protocol Version
+String类型的Server Address
+Unsigned Short类型的Server Port
+VarInt类型的Next state
但实际上通过抓包后发现Protocol Version
与Server Address
仍存在字节,经过测试后发现为Server Address
的VarInt类型的长度数值,因此正确完整的HandShake包结构为:
VarInt类型的Pakect Length
+Packet ID
+VarInt类型的Protocol Version
+VarInt类型的Server Address Length
+String类型的Server Address
+Unsigned Short类型的Server Port
+VarInt类型的Next state
受大小端影响,
Server Port
部分转换为byte内容后顺序可能会受影响,但不影响服务器响应,实测MC客户端以大端排序和模拟客户端以小端排序发送包后均可以得到服务器正确响应。
例如一次抓包得到客户端HandShake十六进制数据为:18 00 fe 05 11 6d 63 2e 67 6f 6f 64 62 6f 79 62 6f 79 2e 74 6f 70 63 dd 01
拆分后可以得到:
18
为VarInt类型的整个数据包长度(不包含18
)——24字节
00
为Packet ID——0x00
fe 05
为VarInt类型的Protocol Version——766
11
为VarInt类型的Server Address的长度——17字节
6d 63 2e 67 6f 6f 64 62 6f 79 62 6f 79 2e 74 6f 70
为Server Address——mc.goodboyboy.top
63 dd
为Unsigned Short类型的Server Port——25565(大端排序)
01
为VarInt类型的Next state——0x01
获取状态
通过下图可以看到Status Request包的结构:
因此整个完整的Status Request包为:
VarInt类型的Pakect Length
+Packet ID
无需带任何数据
通过抓包可以得到01 00
01
为整个包长度(不包含01
)——1个字节
00
为Packet ID,请求服务器状态。
状态响应
从下图可以看出主要的数据载体为JSON
服务器状态响应包结构在wiki上没有很直观展示,只对返回的json进行了展示,经过测试后得出下面结构:
VarInt类型的Pakect Length
+Packet ID
+VarInt类型的JSON数据长度
+JSON数据
将JSON数据解析出来即可得到服务器状态Motd
Ping
在获取完服务器状态后可以直接进行Ping测试,测试精度取决于当前计算机以及实现代码。
从下图中可以看出Ping包的结构:
结构同样是:
VarInt类型的Pakect Length
+Packet ID
+数据
因为只是进行延迟测试,所以数据具体内容不重要,但不能没有。
抓包数据:09 01 00 00 00 00 00 00 2e 5d
通过抓包发现客户端的Ping包包含了8个字节数据,加上1位Pakect Length与Packet ID,总数据包大小为10字节。
推荐使用客户端格式使用8位任意数据。
在发送Ping包后服务器会返回同样的数据包以做应答
在wireshark上可以看到
1849 → 25565 [PSH, ACK] Seq=28 Ack=13939 Win=263424 Len=10
25565 → 1849 [PSH, ACK] Seq=13939 Ack=38 Win=42496 Len=10
数据Data均为09010000000000002e5d
。
参考
Use this card to join MyBlog and participate in a pleasant discussion together .
Welcome to GoodBoyboy 's Blog,wish you a nice day .