PHP Gameserver查询

时间:2014-02-20 20:13:28

标签: php

我有一个脚本我发现查询SRCDS游戏服务器并输出主机名,IP,连接的播放器等信息(注意我已编辑它所以它只显示当前连接的播放器和地图)我希望脚本先ping服务器检查它是否在线,然后继续查询。

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: 

并且不要继续查询以最小化加载页面所需的时间。

2 个答案:

答案 0 :(得分:1)

根据fsockopen的{​​{3}},特别是对于UDP连接,你应该考虑做更多的错误处理:

  

警告

     

UDP套接字有时似乎已打开而没有错误,   即使远程主机无法访问。错误只会变成   当您向套接字读取数据或从套接字写入数据时显而易见。原因   这是因为UDP是一种“无连接”协议,这意味着   操作系统不会尝试建立链接   套接字直到它实际需要发送或接收数据。

答案 1 :(得分:1)

这很可能不会让事情变得更快,但它可能比现在至少要好。但是,我会注意到PHP手册在参考unread_bytes用法时说明了这一点:Note: You shouldn't use this value in a script.您还可以减少对fsockopen的调用的超时(最后一个参数)。 / p>

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'];
}