Difference between revisions of "Server List Ping"
Toastedtruth (talk | contribs) m (→Ping Process: Reference netty rewrite protocol version table for convenience) |
(clarification and formatting) |
||
Line 1: | Line 1: | ||
− | Minecraft supports querying the MOTD, player count, max players and server version via the usual port. Unlike [[Query]], the server list ping interface is always enabled. | + | Minecraft supports querying the MOTD, player count, max players and server version via the usual port. Unlike [[Query]], the server list ping interface is always enabled. The server ping process changed in 1.7 in a non-backwards compatible way, but current servers still support both the [[#Current|new]] and [[#1.6|old]] process. |
− | == | + | == Current == |
− | + | This uses the regular client-server [[protocol]]. For the general packet format, see that article. | |
− | + | === Handshake === | |
+ | |||
+ | First, the client sends a [[Protocol#Handshake|Handshake]] packet with its state set to 1. | ||
{| class="wikitable" | {| class="wikitable" | ||
− | ! Field Name | + | ! Packet ID |
− | |- | + | ! Field Name |
− | | | + | ! Field Type |
− | |- | + | ! Notes |
− | | | + | |- |
− | | | + | |rowspan="4"| 0x00 |
− | + | | Protocol Version | |
− | + | | VarInt | |
+ | | See [[protocol version numbers]] (currently 47, but any version number should be accepted) | ||
+ | |- | ||
+ | | Server Address | ||
+ | | String | ||
+ | | hostname or IP, e.g. localhost or 127.0.0.1 | ||
+ | |- | ||
+ | | Server Port | ||
+ | | Unsigned Short | ||
+ | | default is 25565 | ||
+ | |- | ||
+ | | Next state | ||
+ | | VarInt | ||
+ | | should be 1, for [[Protocol#Status|status]] | ||
+ | |} | ||
− | === | + | === Request === |
− | + | The client follows up with a [[Protocol#Request|Request]] packet. This packet has no fields. | |
{| class="wikitable" | {| class="wikitable" | ||
− | ! Packet ID | + | ! Packet ID |
− | |- | + | ! Field Name |
− | + | ! Field Type | |
− | | | + | ! Notes |
− | + | |- | |
− | + | | 0x00 | |
− | + | |colspan="3"| ''no fields'' | |
− | + | |} | |
− | |||
− | |||
− | |} | ||
− | |||
− | |||
− | + | === Response === | |
− | |||
− | |||
− | |||
− | |||
− | The server should respond with a [[Protocol#Response| | + | The server should respond with a [[Protocol#Response|Response]] packet. |
{| class="wikitable" | {| class="wikitable" | ||
− | ! Packet ID | + | ! Packet ID |
− | |- | + | ! Field Name |
− | + | ! Field Type | |
− | | JSON Response | + | ! Notes |
− | |} | + | |- |
+ | | 0x00 | ||
+ | | JSON Response | ||
+ | | String | ||
+ | | see below | ||
+ | |} | ||
− | The | + | The JSON Response field is a [[wikipedia:JSON|JSON]] object which has the following format: |
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
{ | { | ||
− | + | "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>" | |
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | The ''description'' field | + | The ''description'' field is a [[Chat]] object. |
− | The ''sample'' and ''favicon'' | + | The ''sample'' and ''favicon'' fields are optional. |
− | The ''favicon'' should be a | + | The ''favicon'' should be a [[wikipedia:Portable Network Graphics|PNG]] image that is [[wikipedia:Base64|Base64]] encoded and prepended with <code>data:image/png;base64,</code>. |
− | + | After receiving the Response packet, the client may send the next packet to help calculate the server's latency, or if it is only interested in the above information it can disconnect here. | |
− | + | === Ping === | |
+ | |||
+ | If the process is continued, the client will now send a [[Protocol#Ping|Ping]] packet containing some payload which is not important. | ||
{| class="wikitable" | {| class="wikitable" | ||
− | ! Packet ID | + | ! Packet ID |
− | |- | + | ! Field Name |
− | + | ! Field Type | |
− | | | + | ! Notes |
− | |} | + | |- |
+ | | 0x01 | ||
+ | | Payload | ||
+ | | Long | ||
+ | | May be any number. Notchian clients send the time since epoch in milliseconds. | ||
+ | |} | ||
− | The server will respond with the | + | === Pong === |
+ | |||
+ | The server will respond with the [[Protocol#Pong|Pong]] packet and then close the connection. | ||
{| class="wikitable" | {| class="wikitable" | ||
− | ! Packet ID | + | ! Packet ID |
− | |- | + | ! Field Name |
− | + | ! Field Type | |
− | | | + | ! Notes |
− | |} | + | |- |
+ | | 0x01 | ||
+ | | Payload | ||
+ | | Long | ||
+ | | Should be the same as sent by the client | ||
+ | |} | ||
=== Examples === | === Examples === | ||
Line 111: | Line 137: | ||
== 1.6 == | == 1.6 == | ||
− | === Client | + | This uses a protocol which is compatible with the client-server protocol as it was before the Netty rewrite. Modern servers recognize this protocol by the starting byte of <code>fe</code> instead of the usual <code>00</code>. |
+ | |||
+ | === Client to server === | ||
− | The client initiates a TCP connection to the | + | The client initiates a TCP connection to the server on the standard port. Instead of doing auth and logging in (as detailed in [[Protocol]] and [[Protocol Encryption]]), it sends the following data, expressed in hexadecimal: |
− | # <code>FE</code> | + | # <code>FE</code> — packet identifier for a server list ping |
− | # <code>01</code> | + | # <code>01</code> — server list ping's payload (always 1) |
− | # <code>FA</code> | + | # <code>FA</code> — packet identifier for a plugin message |
− | # <code>00 0B</code> | + | # <code>00 0B</code> — length of following string, in characters, as a short (always 11) |
− | # <code>00 4D 00 43 00 7C 00 50 00 69 00 6E 00 67 00 48 00 6F 00 73 00 74</code> | + | # <code>00 4D 00 43 00 7C 00 50 00 69 00 6E 00 67 00 48 00 6F 00 73 00 74</code> — the string <code>MC|PingHost</code> encoded as a [http://en.wikipedia.org/wiki/UTF-16 UTF-16BE] string |
− | # <code>XX XX</code> | + | # <code>XX XX</code> — length of the rest of the data, as a short. Compute as <code>7 + len(hostname)</code>, where <code>len(hostname)</code> is the number of bytes in the UTF-16BE encoded hostname. |
− | # <code>XX</code> | + | # <code>XX</code> — [[Protocol version numbers#Versions before the Netty rewrite|protocol version]], e.g. <code>4a</code> for the last version (74) |
− | # <code>XX XX</code> | + | # <code>XX XX</code> — length of following string, in characters, as a short |
− | # <code>...</code> | + | # <code>...</code> — hostname the client is connecting to, encoded as a [http://en.wikipedia.org/wiki/UTF-16 UTF-16BE] string |
− | # <code>XX XX XX XX</code> | + | # <code>XX XX XX XX</code> — port the client is connecting to, as an int. |
− | All | + | All data types are big-endian. |
− | + | Example packet dump: | |
− | + | 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. | |
− | === Server | + | === Server to client === |
− | The server responds with a | + | The server responds with a 0xFF kick packet. The packet begins with a single byte identifier <code>ff</code>, then a two-byte big endian short giving the length of the following string in characters. You can actually ignore the length because the server closes the connection after the response is sent. |
After the first 3 bytes, the packet is a UTF-16BE string. It begins with two characters: <code>§1</code>, followed by a null character. On the wire these look like <code>00 a7 00 31 00 00</code>. | After the first 3 bytes, the packet is a UTF-16BE string. It begins with two characters: <code>§1</code>, followed by a null character. On the wire these look like <code>00 a7 00 31 00 00</code>. | ||
Line 143: | Line 171: | ||
The remainder is null character (that is <code>00 00</code>) delimited fields: | The remainder is null character (that is <code>00 00</code>) delimited fields: | ||
− | # Protocol version (e.g. <code> | + | # Protocol version (e.g. <code>74</code>) |
− | # Minecraft server version (e.g. <code>1. | + | # Minecraft server version (e.g. <code>1.8.7</code>) |
# Message of the day (e.g. <code>A Minecraft Server</code>) | # Message of the day (e.g. <code>A Minecraft Server</code>) | ||
# Current player count | # Current player count | ||
Line 151: | Line 179: | ||
The entire packet looks something like this: | The entire packet looks something like this: | ||
− | + | <---> first character | |
− | + | 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 | |
=== Examples === | === Examples === | ||
Line 163: | Line 191: | ||
* [https://github.com/winny-/mcstat PHP] | * [https://github.com/winny-/mcstat PHP] | ||
− | == 1.4 | + | == 1.4 to 1.5 == |
− | Prior to the Minecraft 1.6, the client | + | Prior to the Minecraft 1.6, the client to server operation is much simpler, and only sends <code>FE 01</code>, with none of the following data. |
=== Examples === | === Examples === | ||
Line 173: | Line 201: | ||
* [https://gist.github.com/6223787 C#] | * [https://gist.github.com/6223787 C#] | ||
− | == Beta 1.8 | + | == Beta 1.8 to 1.3 == |
Prior to Minecraft 1.4, the client only sends <code>FE</code>. | Prior to Minecraft 1.4, the client only sends <code>FE</code>. | ||
Line 185: | Line 213: | ||
The entire packet looks something like this: | The entire packet looks something like this: | ||
− | + | <---> first character | |
− | + | 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 |
Revision as of 14:40, 7 July 2015
Minecraft supports querying the MOTD, player count, max players and server version via the usual port. Unlike Query, the server list ping interface is always enabled. The server ping process changed in 1.7 in a non-backwards compatible way, but current servers still support both the new and old process.
Contents
Current
This uses the regular client-server protocol. For the general packet format, see that article.
Handshake
First, the client sends a Handshake packet with its state set to 1.
Packet ID | Field Name | Field Type | Notes |
---|---|---|---|
0x00 | Protocol Version | VarInt | See protocol version numbers (currently 47, but any version number should be accepted) |
Server Address | String | hostname or IP, e.g. localhost or 127.0.0.1 | |
Server Port | Unsigned Short | default is 25565 | |
Next state | VarInt | should be 1, for status |
Request
The client follows up with a Request packet. This packet has no fields.
Packet ID | Field Name | Field Type | Notes |
---|---|---|---|
0x00 | no fields |
Response
The server should respond with a Response packet.
Packet ID | Field Name | Field Type | Notes |
---|---|---|---|
0x00 | JSON Response | String | see below |
The JSON Response field is a JSON object which has the following format:
{
"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>"
}
The description field is a Chat object.
The sample and favicon fields are optional.
The favicon should be a PNG image that is Base64 encoded and prepended with data:image/png;base64,
.
After receiving the Response packet, the client may send the next packet to help calculate the server's latency, or if it is only interested in the above information it can disconnect here.
Ping
If the process is continued, the client will now send a Ping packet containing some payload which is not important.
Packet ID | Field Name | Field Type | Notes |
---|---|---|---|
0x01 | Payload | Long | May be any number. Notchian clients send the time since epoch in milliseconds. |
Pong
The server will respond with the Pong packet and then close the connection.
Packet ID | Field Name | Field Type | Notes |
---|---|---|---|
0x01 | Payload | Long | Should be the same as sent by the client |
Examples
1.6
This uses a protocol which is compatible with the client-server protocol as it was before the Netty rewrite. Modern servers recognize this protocol by the starting byte of fe
instead of the usual 00
.
Client to server
The client initiates a TCP connection to the server on the standard port. Instead of doing auth and logging in (as detailed in Protocol and Protocol Encryption), it sends the following data, expressed in hexadecimal:
FE
— packet identifier for a server list ping01
— server list ping's payload (always 1)FA
— packet identifier for a plugin message00 0B
— length of following string, in characters, as a short (always 11)00 4D 00 43 00 7C 00 50 00 69 00 6E 00 67 00 48 00 6F 00 73 00 74
— the stringMC|PingHost
encoded as a UTF-16BE stringXX XX
— length of the rest of the data, as a short. Compute as7 + len(hostname)
, wherelen(hostname)
is the number of bytes in the UTF-16BE encoded hostname.XX
— protocol version, e.g.4a
for the last version (74)XX XX
— length of following string, in characters, as a short...
— hostname the client is connecting to, encoded as a UTF-16BE stringXX XX XX XX
— port the client is connecting to, as an int.
All data types are big-endian.
Example packet dump:
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.
Server to client
The server responds with a 0xFF kick packet. The packet begins with a single byte identifier ff
, then a two-byte big endian short giving the length of the following string in characters. You can actually ignore the length because the server closes the connection after the response is sent.
After the first 3 bytes, the packet is a UTF-16BE string. It begins with two characters: §1
, followed by a null character. On the wire these look like 00 a7 00 31 00 00
.
The remainder is null character (that is 00 00
) delimited fields:
- Protocol version (e.g.
74
) - Minecraft server version (e.g.
1.8.7
) - Message of the day (e.g.
A Minecraft Server
) - Current player count
- Max players
The entire packet looks something like this:
<---> first character 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
Examples
1.4 to 1.5
Prior to the Minecraft 1.6, the client to server operation is much simpler, and only sends FE 01
, with none of the following data.
Examples
Beta 1.8 to 1.3
Prior to Minecraft 1.4, the client only sends FE
.
Additionally, the response from the server only contains 3 fields delimited by §
:
- Message of the day (e.g.
A Minecraft Server
) - Current player count
- Max players
The entire packet looks something like this:
<---> first character 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