Since 1.8 servers can now respond to ping requests, I decided to try to make a PHP script that will ping the server and get the number of players online. Keep in mind that I've never done anything with sockets in PHP before, so if someone sees something wrong or bad, please let me know. Code: $host = "hostnamehere.com"; $port = 25565; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $connected = socket_connect($socket, $host, $port); if ($connected) { socket_send($socket, "\xFE", 1, 0); $data = ""; $result = socket_recv($socket, &$data, 50, 0); socket_close($socket); if ($result != false && substr($data, 0, 1) == "\xFF") { $info = explode("\xA7", mb_convert_encoding(substr($data,1), "iso-8859-1", "utf-16be")); $serverName = substr($info[0], 1); $playersOnline = $info[1]; $playersMax = $info[2]; echo "Server: $serverName<br/>Players Online: $playersOnline/$playersMax"; } else { echo "Failed to receive data"; } } else { echo "Failed to connect"; } I'm unsure about the character decoding, but it seems to work. Also, there was a character in the server name (0x15) that I cut off, not sure why that is there. Otherwise it seems to work great.
Just had to try it out to see what ifo the server did send. Not much as it turns out. Would have been nice to see a whitelist flag. I did add a ping measurement. Seems it shows way of compared to the ingame measurement u get on the serverlist. To the server I tried it to i get about 25/30ms with ingame browser(some odd high/low) but with the php query i get even better but mostly worse. It does jump around . Either way it was just a test. Dunno why the ping gets so random values. PHP: $host = "XXXXXXXXXX";$port = 25565;$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);$connected = socket_connect($socket, $host, $port);if ($connected) { $ping_start = microtime(true); socket_send($socket, "\xFE", 1, 0); $data = ""; $result = socket_recv($socket, &$data, 50, 0);$ping_end = microtime(true); socket_close($socket); if ($result != false && substr($data, 0, 1) == "\xFF") { $info = explode("\xA7", mb_convert_encoding(substr($data,1), "iso-8859-1", "utf-16be")); $serverName = substr($info[0], 1); $playersOnline = $info[1]; $playersMax = $info[2]; $ping = round(($ping_end - $ping_start) * 1000); echo "Server: $serverName<br/> Address: $host<br/> Port: $port<br/> Players Online: $playersOnline/$playersMax <br/> Ping: $ping ms<br/>"; } else { echo "Failed to receive data"; }} else { echo "Failed to connect";} Just tried some long motd messages. seems 50 is a bit short and you would risk loosing maxplayerinfo or more from the string. I would recommend changing 50 to 150 in this row.. PHP: $result = socket_recv($socket, &$data, 150, 0); Long motd mess up ingame serverinfo to. Regardless off gui scale chosen. 150 should be enough to show all needed.
With both of them, I get: This happened with a server that might be on or off, and it happened with a server that was on. What do you think's wrong?
The socket functions require that php_sockets.dll be enabled under Windows. Here is a modification that does not require this: Code: <?php $host = "example.com"; $port = 25565; $socket = @fsockopen($host, $port); if ($socket !== false) { @fwrite($socket, "\xFE"); $data = ""; $data = @fread($socket, 1024); @fclose($socket); if ($data !== false && substr($data, 0, 1) == "\xFF") { $info = explode("\xA7", mb_convert_encoding(substr($data,1), "iso-8859-1", "utf-16be")); $serverName = substr($info[0], 1); $playersOnline = $info[1]; $playersMax = $info[2]; echo "Server: $serverName<br/>Players Online: $playersOnline/$playersMax"; } else { // Server did not send back proper data, or reading from socket failed. echo "Failed to receive data"; } } else { // Can't connect. Server is probably down. echo "Failed to connect"; } ?>
Hmm, I Tried the new version, and the socket part worked, except that a server that I know is up (I'm on it) is giving the failed to connect message.
You're doing it wrong. What you think is a "strange character" before the server name is actually the length field. Before you do the conversion from utf-16 it's two bytes, a 16 bit signed integer in big endian format, that tells you how many bytes the following string has.
Is there a firewall blocking the PHP server from establishing a connection out (Windows Firewall enabled?). Is this hosted locally or with a hosting provider? A lot of web hosts restrict outbound access from websites and require you to request ports to be opened.
Hosting provider. I wouldn't think about the port thing, mainly because i am paying a huge amount of money for it. It isn't a firewall I think.
Most hosting providers restrict outbound ports nowadays on the web server. Most websites only need to connect to 80, 25, 443, 3306 and a handful of others. Just contact your hosting provider and ask them to make sure the outbound port is open.
Looks good, thanks for the script I was looking for something simple to check if my server was up and this was it! With PHP i always recommend you develop with strict error reporting (a simple error_reporting(E_ALL); at the top of your script will do fine). On the socket_recv you need to remove the `&` from in front of the buf variable, call time pass by reference was depreciated and removing it will still provide the same behavior you were expecting.
nope, E_STRICT only became part of E_ALL in PHP 5.4 (the latest stable is in the PHP 5.3 series) The PHP documentation suggest using error_reporting(-1);
You guys might also want to check out this page: http://mc.kev009.com/Protocol#Server_List_Ping_.280xFE.29 It has documentation of every packet, including the server ping list packet. It also has a link to very simple code to pull this info in PHP or Python. Very useful stuff.