[PHP] Server Query

Dieses Thema im Forum "Programmierung" wurde erstellt von Zahl, 1. November 2012.

Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. Zahl
    Offline

    Zahl

    Registriert seit:
    10. Juli 2011
    Beiträge:
    214
    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:
    1. <?php
    2.  
    3. /**
    4.  * Minecraft server query by Zahl
    5.  * Works with 1.4 and pre-1.4 servers
    6.  * Returns an array on success, string describing the error on failure
    7.  */
    8. function queryServer($address, $port)
    9. {
    10.     $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    11.     if ($socket === false) {
    12.         return 'Error creating socket';
    13.     }
    14.    
    15.     @socket_set_nonblock($socket);
    16.  
    17.     @socket_connect($socket, $address, $port);
    18.     $r = $w = $e = array($socket);
    19.     @socket_select($r, $w, $e, 3, 0); // Try connecting for 3 seconds max.
    20.     if (count($w) !== 1) {
    21.         @socket_close($socket);
    22.         return 'offline';
    23.     }
    24.  
    25.     @socket_set_block($socket);
    26.    
    27.     $start = microtime(true);
    28.     $result = executeQuery($socket);
    29.    
    30.     if (is_array($result)) {
    31.         $result['ping'] = round((microtime(true) - $start) * 1000);
    32.     }
    33.    
    34.     @socket_close($socket);
    35.     return $result;
    36. }
    37.  
    38. function executeQuery($socket)
    39. {
    40.     // Write timeout, so that crashed servers will not make this script hang forever
    41.     socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 2, 'usec' => 0));
    42.     // Send query
    43.     $ret = socket_write($socket, "\xFE\x01", 2);
    44.     if ($ret !== 2) {
    45.         return 'Error sending query';
    46.     }
    47.     // Read timeout, see above
    48.     socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 3, 'usec' => 0));
    49.     // Wait for reply header
    50.     $ret = @socket_recv($socket, $header, 3, MSG_WAITALL);
    51.     if ($ret !== 3) {
    52.         return 'Reply header incomplete';
    53.     }
    54.     if (ord($header{0}) != 255) {
    55.         return 'Reply has unexpected packet ID ' . ord($header{0});
    56.     }
    57.     $reportedLen = ((ord($header{1}) << 8) + ord($header{2})) * 2; // in bytes (almost)
    58.     if ($reportedLen === 0) {
    59.         return 'Reply has no payload';
    60.     }
    61.     // Decrease timeout even more as this part should already be floating around in the tcp/ip stack
    62.     socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 0, 'usec' => 50000));
    63.     $payloadLen = @socket_recv($socket, $payload, $reportedLen, MSG_WAITALL);
    64.     if ($payloadLen < $reportedLen) {
    65.         return 'Reply is shorter than header says! Should be' . $reportedLen . ' but is ' . $payloadLen;
    66.     }
    67.    
    68.     // Parse reply
    69.     if ($payloadLen > 1 && ord($payload{0}) === 0 && ord($payload{1}) === 0xA7) {
    70.         // Server is 1.4+
    71.         $data = mb_convert_encoding(substr($payload, 2), 'UTF-8', 'UTF-16BE');
    72.         // Above needs the multibyte string functions which should be available on any halfway modern php installation.
    73.         // Also, the UTF-16BE encoding must be supported. Get all encodings your installation supports:
    74.         //print_r(mb_list_encodings());
    75.  
    76.         $data = explode("\0", $data);
    77.        
    78.         if (count($data) < 6) {
    79.             return 'Returned data has less than 6 sections (' . count($data) . "):\n" . $data;
    80.         }
    81.         //if ($data[0] == 1) <--- data[0] is the query protocol version. currently only 1 exists, might need to check that in the future
    82.         return array(
    83.             'protocol'      => $data[1], // Minecraft protocol version. 1.4.x is 47
    84.             'version'       => $data[2], // Server version as string, i.e. "1.4.2"
    85.             'name'          => $data[3], // Server name, might include color/formatting codes
    86.             'players'       => $data[4], // Number of players online
    87.             'maxplayers'    => $data[5]  // Max number of players
    88.         );
    89.     }
    90.  
    91.     // ########################
    92.     // Server is 1.3.2 or older
    93.    
    94.     $data = mb_convert_encoding($payload, 'UTF-8', 'UTF-16BE');
    95.     // Above needs the multibyte string functions which should be available on any halfway modern php installation.
    96.     // Also, the UTF-16BE encoding must be supported. Get all encodings your installation supports:
    97.     //print_r(mb_list_encodings());
    98.    
    99.     $data = explode('§', $data);
    100.     if (count($data) < 3) {
    101.         return 'Returned data has less than 3 sections';
    102.     }
    103.    
    104.     return array(
    105.         'name'          => $data[0],
    106.         'players'       => $data[1],
    107.         'maxplayers'    => $data[2]
    108.     );
    109. }
    110.  
    111. /**
    112.  * Remove color and formatting from a String
    113.  * e.g. "§cColorful §fMessage" => "Colorful Message"
    114.  */
    115. function stripFormat($string)
    116. {
    117.     return preg_replace('/§./', '', $string);
    118. }
    119.  
    120.  
    121. // #######################################
    122. // DEMO PART:
    123.  
    124. // If you're running via browser rather than command line
    125. if (isset($_SERVER['REMOTE_ADDR'])) Header('Content-Type: text/plain; charset=utf-8');
    126.  
    127.  
    128. $servers = array(
    129.     'spieleplanet.eu'       => 25565,
    130.     'S.wbkbuild-mc.de'      => 25570,
    131.     's.wbkbuild-mc.de'      => 25565,
    132.     '4.4.4.4'               => 25565 // One that is offline for sure...
    133. );
    134.  
    135. foreach ($servers as $addr => $port) {
    136.     $ret = queryServer($addr, $port);
    137.     if (is_array($ret)) { // ONLINE
    138.         if (isset($ret['version'])) { // version field set - it's 1.4 or newer
    139.             $ret['name'] = stripFormat($ret['name']);
    140.             echo " :-) $addr:$port is '{$ret['name']}', with {$ret['players']} of {$ret['maxplayers']} players online, Ping: {$ret['ping']}. ({$ret['version']})\n";
    141.         } else { // 1.3.2 or older
    142.             echo " :-) $addr:$port is '{$ret['name']}', with {$ret['players']} of {$ret['maxplayers']} players online, Ping: {$ret['ping']}.\n";
    143.         }
    144.     } else { // OFFLINE/ERROR
    145.         echo " *** $addr:$port did not reply: $ret\n";
    146.     }
    147. }
    148. echo "DONE\n";
    149. exit(0);
     
    #1
  2. Crafter6432
    Offline

    Crafter6432

    Registriert seit:
    22. Dezember 2011
    Beiträge:
    686
  3. Let's Mine
    Offline

    Let's Mine Ehem. Teammitglied

    Registriert seit:
    1. Dezember 2011
    Beiträge:
    421
    Ort:
    Let's Mine
    Minecraft:
    LetsMine
    Das ist etwas völlig anderes.
     
    #3
  4. At-M
    Offline

    At-M

    Registriert seit:
    30. März 2012
    Beiträge:
    194
    Ort:
    An der Nordsee
    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 ?>
     
    #4
Status des Themas:
Es sind keine weiteren Antworten möglich.