PHP客户端确认(BattlEye)

时间:2017-12-21 16:33:34

标签: php sockets websocket protocols

https://www.battleye.com/downloads/BERConProtocol.txt

以下代码是通过游戏服务器的远程连接。 (RCon)BattlEye协议(上面的链接)。基本上它只是在套接字上读写。

脚本将命令比如说测试 发送到服务器。

正如你所看到的,它是一个无趣的循环。

睡眠1秒后,应发送cmd并重新开始循环。

$pass =        "my_rcon_pw";
$ip =          "12.34.56.78";
$port =        2309;

//

$authCRC = sprintf('%x', crc32(chr(255).chr(00).trim($pass)));
$authCRC = array(substr($authCRC,-2,2), substr($authCRC,-4,2), substr($authCRC,-6,2), substr($authCRC,0,2));

$loginMsg = 'BE'.chr(hexdec($authCRC[0])).chr(hexdec($authCRC[1])).chr(hexdec($authCRC[2])).chr(hexdec($authCRC[3]));
$loginMsg .= chr(hexdec('ff')).chr(hexdec('00')).trim($pass);

$hbMsg = 'BE'.chr(hexdec('7d')).chr(hexdec('8f')).chr(hexdec('ef')).chr(hexdec('73'));
$hbMsg .= chr(hexdec('ff')).chr(hexdec('02')).chr(hexdec('00'));

//

$server = @fsockopen( "udp://" . $ip, $port, $errno, $errstr, 1 );

if( $server === false ) throw new \Exception( 'Could not bind to socket: ' . $errstr );

//

$sent = fwrite( $server, $loginMsg );

if( $sent === false ) throw new \Exception( 'Failed to send login!' );

$result = fread( $server, 16 );

if( @ord( $result[strlen( $result ) - 1] ) == 0 ) throw new \Exception( 'Login failed, wrong password or wrong port!' );

//

for(;;)
{
    sleep(1);

    $command =    "say -1 TEST";

    $msgCRC = sprintf('%x', crc32(chr(255).chr(01).chr(hexdec(sprintf('%01b', 0))).trim($command)));
    $msgCRC = array(substr($msgCRC,-2,2),substr($msgCRC,-4,2),substr($msgCRC,-6,2),substr($msgCRC,0,2));

    $cmdHead = 'BE'.chr(hexdec($msgCRC[0])).chr(hexdec($msgCRC[1])).chr(hexdec($msgCRC[2])).chr(hexdec($msgCRC[3])).chr(hexdec('ff')).chr(hexdec('01')).chr(hexdec(sprintf('%01b', 0)));
    $cmdMsg = $cmdHead.trim($command);

    //

    $cmd = fwrite( $server, $cmdMsg );

    if( $cmd === false ) throw new \Exception( 'Failed to send command!' );
}  

9-10秒后,服务器将关闭客户端的连接。发生这种情况是因为客户端需要向他仍然活着的服务器发送验证。

以下代码添加"心跳"约每10秒进入循环。

for(;;)
{
    if( !isset( $i ) ) $i = 0;

    sleep(1);

    $command =    "say -1 TEST";

    $msgCRC = sprintf('%x', crc32(chr(255).chr(01).chr(hexdec(sprintf('%01b', 0))).trim($command)));
    $msgCRC = array(substr($msgCRC,-2,2),substr($msgCRC,-4,2),substr($msgCRC,-6,2),substr($msgCRC,0,2));

    $cmdHead = 'BE'.chr(hexdec($msgCRC[0])).chr(hexdec($msgCRC[1])).chr(hexdec($msgCRC[2])).chr(hexdec($msgCRC[3])).chr(hexdec('ff')).chr(hexdec('01')).chr(hexdec(sprintf('%01b', 0)));
    $cmdMsg = $cmdHead.trim($command);

    //

    $cmd = fwrite( $server, $cmdMsg );

    if( $cmd === false ) throw new \Exception( 'Failed to send command!' );

    $i++;

    //

    if( $i == 9 )
    {
        $hb = fwrite( $server, $hbMsg );

        if( $hb === false ) throw new \Exception( 'Failed to send heartbeat!' );

        unset( $i );
    }
}  

奇怪的是,这种心跳只能一次。 这意味着客户在开始后不超过10秒就超时,现在开始后不到20秒左右。

这就是这段代码的全部问题。

我在PHP控制台中运行它 - 所以没有最大执行时间或其他任何内容。

目标是将其作为"执行"客户端和服务器之间的连接。

问题

与协议一样,客户端需要确认服务器的数据包或将超时。

如何确认协议中描述的传入数据包?

我的心跳包到服务器可能有问题吗?

我真的很感激任何提示或帮助:)

到目前为止,感谢德国人的问候!

0 个答案:

没有答案