2014-02-20 48 views
0

我有一個劇本,我發現查詢SRCDS遊戲服務器和輸出信息,如主機名,IP,連接播放器等(注意:我已經編輯它,所以它只能裏顯示當前連接播放器和地圖)我想劇本首先ping服務器以檢查它是否在線,然後繼續查詢。PHP遊戲服務器查詢

PHP腳本

function source_query($ip){ 
$cut = explode(":", $ip); 
$HL2_address = $cut[0]; 
$HL2_port = $cut[1]; 

$HL2_command = "\377\377\377\377TSource Engine Query\0"; 

$HL2_socket = fsockopen("udp://".$HL2_address, $HL2_port, $errno, $errstr,3); 
fwrite($HL2_socket, $HL2_command); 
$JunkHead = fread($HL2_socket,4); 
$CheckStatus = socket_get_status($HL2_socket); 

if($CheckStatus["unread_bytes"] == 0)return 0; 

$do = 1; 
while($do){ 
    $str = fread($HL2_socket,1); 
    $HL2_stats.= $str; 
    $status = socket_get_status($HL2_socket); 
    if($status["unread_bytes"] == 0){ 
      $do = 0; 
    } 
} 
fclose($HL2_socket); 

$x = 0; 
while ($x <= strlen($HL2_stats)){ 
    $x++; 
    $result.= substr($HL2_stats, $x, 1);  
} 

// ord (string $string); 
$result = str_split($result); 
$info['network'] = ord($result[0]);$char = 1; 
while(ord($result[$char]) != "%00"){$info['name'] .= $result[$char];$char++;}$char++; 
while(ord($result[$char]) != "%00"){$info['map'] .= $result[$char];$char++;}$char++; 
while(ord($result[$char]) != "%00"){$info['dir'] .= $result[$char];$char++;}$char++; 
while(ord($result[$char]) != "%00"){$info['description'] .= $result[$char];$char++;}$char++; 
$info['appid'] = ord($result[$char].$result[($char+1)]);$char += 2;   
$info['players'] = ord($result[$char]);$char++;  
$info['max'] = ord($result[$char]);$char++;  
$info['bots'] = ord($result[$char]);$char++;  
$info['dedicated'] = ord($result[$char]);$char++;  
$info['os'] = chr(ord($result[$char]));$char++;  
$info['password'] = ord($result[$char]);$char++;  
$info['secure'] = ord($result[$char]);$char++;  
while(ord($result[$char]) != "%00"){$info['version'] .= $result[$char];$char++;} 

return $info; 
} 

顯示代碼

include 'status.php'; // name of file including above script 
$q = source_query('ip:port'); // replaced with real IP address and port 
echo "Players: " .$q['players']; 
echo "/" .$q['max']; 
echo "<br>"; 
echo "Map: ".$q['map']; 

澄清:當服務器在線這個腳本作品在返回當前連接的球員和當前地圖精細正在播放。當服務器處於脫機狀態時,會加載一段時間,然後僅打印

Players:/
Map: 

我希望服務器事先被ping通。如果是網上確實如上述,但如果是離線我希望它回聲「脫機」,去掉

Players:/
Map: 

,不與查詢不斷減少的時間長度需要加載頁。

回答

1

這很可能不會加快整個過程,但可能比現在至少要好。不過,我會注意的是,PHP手冊中提到的unread_bytes使用這樣說:Note: You shouldn't use this value in a script.你也可以減少對呼叫超時(最後一個參數)fsockopen

function ping($host) 
{ 
    exec(sprintf('ping -c 1 -W 5 %s', escapeshellarg($host)), $res, $rval); 
    return $rval === 0; 
} 

$HL2_command = "\377\377\377\377TSource Engine Query\0"; 

if(!ping($HL2_address)) 
{ 
    return 0; 
} 

$HL2_socket = fsockopen("udp://".$HL2_address, $HL2_port, $errno, $errstr,3); 

顯示代碼

include 'status.php'; // name of file including above script 
$q = source_query('ip:port'); // replaced with real IP address and port 

if($q === 0) 
{ 
    echo "Offline"; 
} 
else 
{ 
    echo "Players: " .$q['players']; 
    echo "/" .$q['max']; 
    echo "<br>"; 
    echo "Map: ".$q['map']; 
} 
+0

這工作,提供的服務器是在線還是存在。但是,它沒有如上所述那樣做。如果服務器處於脫機狀態,則會嘗試查詢需要很長時間的服務器。這就是爲什麼我想包含ping功能來檢查它是否在線或沒有進行任何查詢之前! – JakeGriffin

+0

@JakeGriffin你對「離線」的定義究竟是什麼?整個服務器都關閉了?特定端口無法訪問?你會得到一個空的答覆?有可能確定服務器是否「脫機」可能需要一點時間。這就是爲什麼我建議降低超時時間。 –

+0

「離線」我的意思是以上所有。例如,如果我選擇192.168.1.1:80並且端口80上沒有任何內容運行,則頁面加載「離線」需要很長時間。預先ping通地址是否更加可行,以便在查詢之前檢查是否有實際存在的地址並進行響應?我不知道這是否合理。此外,超時設置爲4秒,但如果頁面正在查詢不在/離線的內容,頁面加載需要更長的時間。看看[this](http://www.griffingaming.co.uk/test.php) - 注意加載需要很長時間。 – JakeGriffin

1

根據fsockopenmanual,尤其是對UDP連接,您應該考慮做更多的錯誤處理:

警告

UDP套接字有時會出現沒有錯誤已經打開, 甚至如果遠程主機不可訪問。當您向套接字讀取數據或從套接字寫入數據時,該錯誤只會變爲 。造成這種情況的原因 是因爲UDP是「無連接」協議,這意味着 操作系統不會嘗試建立一個鏈接, 插座,直至實際需要發送或接收數據。