сокеты — подтверждение клиента PHP (BattlEye)

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 — так что нет максимального времени выполнения или чего-то еще.

Цель состоит в том, чтобы запустить это как «постоянное» соединение между клиентом и сервером.


Проблема

Как и в протоколе, клиент должен подтвердить пакеты сервера или истечет время ожидания.

Как я могу подтвердить входящие пакеты, как описано в протоколе?

И может быть что-то не так с моим пакетом пульса на сервер?


Буду очень признателен за любой совет или помощь 🙂

Пока спасибо и немецкие поздравления!

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]