• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

[PHP] Server Query

Status
Für weitere Antworten geschlossen.

Zahl

Vorarbeiter
Registriert
10 Juli 2011
Beiträge
213
Diamanten
0
Dieses Script stellt eine Funktion (mit zwei Hilfsfunktionen) bereit, um einen Server nach der Spieleranzahl etc. abzufragen.
Es ist kompatibel mit dem Queryformat von 1.3.2 und älter, sowie der neuen Version von 1.4.

Disclaimer
Dieses Script wird so wie es ist angeboten. Wer nicht weiß was das ist, oder wie man es verwendet, drückt jetzt bitte die Zurücktaste. Alle Posts, die keine direkten Bug-Reports oder relevante Verbesserungsvorschläge sind, werden zumindest von mir nicht beantwortet.

PHP:
<?php

/**
 * Minecraft server query by Zahl
 * Works with 1.4 and pre-1.4 servers
 * Returns an array on success, string describing the error on failure
 */
function queryServer($address, $port)
{
	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	if ($socket === false) {
		return 'Error creating socket';
	}
	
	@socket_set_nonblock($socket);

	@socket_connect($socket, $address, $port);
	$r = $w = $e = array($socket);
	@socket_select($r, $w, $e, 3, 0); // Try connecting for 3 seconds max.
	if (count($w) !== 1) {
		@socket_close($socket);
		return 'offline';
	}

	@socket_set_block($socket);
	
	$start = microtime(true);
	$result = executeQuery($socket);
	
	if (is_array($result)) {
		$result['ping'] = round((microtime(true) - $start) * 1000);
	}
	
	@socket_close($socket);
	return $result;
}

function executeQuery($socket)
{
	// Write timeout, so that crashed servers will not make this script hang forever
	socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 2, 'usec' => 0));
	// Send query
	$ret = socket_write($socket, "\xFE\x01", 2);
	if ($ret !== 2) {
		return 'Error sending query';
	}
	// Read timeout, see above
	socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 3, 'usec' => 0));
	// Wait for reply header
	$ret = @socket_recv($socket, $header, 3, MSG_WAITALL);
	if ($ret !== 3) {
		return 'Reply header incomplete';
	}
	if (ord($header{0}) != 255) {
		return 'Reply has unexpected packet ID ' . ord($header{0});
	}
	$reportedLen = ((ord($header{1}) << 8) + ord($header{2})) * 2; // in bytes (almost)
	if ($reportedLen === 0) {
		return 'Reply has no payload';
	}
	// Decrease timeout even more as this part should already be floating around in the tcp/ip stack
	socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 0, 'usec' => 50000));
	$payloadLen = @socket_recv($socket, $payload, $reportedLen, MSG_WAITALL);
	if ($payloadLen < $reportedLen) {
		return 'Reply is shorter than header says! Should be' . $reportedLen . ' but is ' . $payloadLen;
	}
	
	// Parse reply
	if ($payloadLen > 1 && ord($payload{0}) === 0 && ord($payload{1}) === 0xA7) {
		// Server is 1.4+
		$data = mb_convert_encoding(substr($payload, 2), 'UTF-8', 'UTF-16BE');
		// Above needs the multibyte string functions which should be available on any halfway modern php installation.
		// Also, the UTF-16BE encoding must be supported. Get all encodings your installation supports:
		//print_r(mb_list_encodings());

		$data = explode("\0", $data);
		
		if (count($data) < 6) {
			return 'Returned data has less than 6 sections (' . count($data) . "):\n" . $data;
		}
		//if ($data[0] == 1) <--- data[0] is the query protocol version. currently only 1 exists, might need to check that in the future
		return array(
			'protocol'		=> $data[1], // Minecraft protocol version. 1.4.x is 47
			'version'		=> $data[2], // Server version as string, i.e. "1.4.2"
			'name'			=> $data[3], // Server name, might include color/formatting codes
			'players'		=> $data[4], // Number of players online
			'maxplayers'	=> $data[5]  // Max number of players
		);
	}

	// ########################
	// Server is 1.3.2 or older
	
	$data = mb_convert_encoding($payload, 'UTF-8', 'UTF-16BE');
	// Above needs the multibyte string functions which should be available on any halfway modern php installation.
	// Also, the UTF-16BE encoding must be supported. Get all encodings your installation supports:
	//print_r(mb_list_encodings());
	
	$data = explode('§', $data);
	if (count($data) < 3) {
		return 'Returned data has less than 3 sections';
	}
	
	return array(
		'name'			=> $data[0],
		'players'		=> $data[1],
		'maxplayers'	=> $data[2]
	);
}

/**
 * Remove color and formatting from a String
 * e.g. "§cColorful §fMessage" => "Colorful Message"
 */
function stripFormat($string)
{
	return preg_replace('/§./', '', $string);
}


// #######################################
// DEMO PART:

// If you're running via browser rather than command line
if (isset($_SERVER['REMOTE_ADDR'])) Header('Content-Type: text/plain; charset=utf-8');


$servers = array(
	'spieleplanet.eu'		=> 25565,
	'S.wbkbuild-mc.de'		=> 25570,
	's.wbkbuild-mc.de'		=> 25565,
	'4.4.4.4'				=> 25565 // One that is offline for sure...
);

foreach ($servers as $addr => $port) {
	$ret = queryServer($addr, $port);
	if (is_array($ret)) { // ONLINE
		if (isset($ret['version'])) { // version field set - it's 1.4 or newer
			$ret['name'] = stripFormat($ret['name']);
			echo " :-) $addr:$port is '{$ret['name']}', with {$ret['players']} of {$ret['maxplayers']} players online, Ping: {$ret['ping']}. ({$ret['version']})\n";
		} else { // 1.3.2 or older
			echo " :-) $addr:$port is '{$ret['name']}', with {$ret['players']} of {$ret['maxplayers']} players online, Ping: {$ret['ping']}.\n";
		}
	} else { // OFFLINE/ERROR
		echo " *** $addr:$port did not reply: $ret\n";
	}
}
echo "DONE\n";
exit(0);
 
Zuletzt bearbeitet:

At-M

Miner
Registriert
30 März 2012
Beiträge
186
Diamanten
0
Minecraft
At_M
sehrgeil! danke :)

mein script funktioniert seit 1.4 nichtmehr so wies soll..

MUSS man den port angeben oder könnte man den auch aus dem script weglassen?


edit:

am ende fehlt nen ?>
 
Zuletzt bearbeitet:
Status
Für weitere Antworten geschlossen.
Oben