https://www.battleye.com/downloads/BERConProtocol.txt
Следующий код представляет собой удаленное соединение с игровым сервером через. (RCon) Протокол BattlEye (ссылка выше). В основном это просто чтение и запись в сокет.
Скрипт отправляет команду скажи -1 ТЕСТ на сервер.
Как видите, это бесконечный цикл.
После сна в течение 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 — так что нет максимального времени выполнения или чего-то еще.
Цель состоит в том, чтобы запустить это как «постоянное» соединение между клиентом и сервером.
Проблема
Как и в протоколе, клиент должен подтвердить пакеты сервера или истечет время ожидания.
Как я могу подтвердить входящие пакеты, как описано в протоколе?
И может быть что-то не так с моим пакетом пульса на сервер?
Буду очень признателен за любой совет или помощь 🙂
Пока спасибо и немецкие поздравления!
Задача ещё не решена.
Других решений пока нет …