Почему мой php SSE файл на сервере продолжает работать, когда браузер закрыт, если ничего не отправлено? - PullRequest
3 голосов
/ 06 июня 2019

У меня странное поведение с SSE.

У меня есть 2 файла, один для стороны сервера и один для клиента браузера.

serverside.php это:

<?php
  header('Content-Type: text/event-stream');
  header('Cache-Control: no-cache');
  ob_end_clean();

  while( true ) {
    set_time_limit(30);

    $time = date('d/m/Y H:i:s');

     echo 'data: ' . $time . "\n\n";
     flush();

    error_log('i am here!');
    sleep(1);
   }
?>

и файл на стороне клиента это:

<!DOCTYPE html>
<html>
<body>

<div id="result"></div>
<script>
    var source;

    if(typeof(EventSource) === "undefined") {
      alert('Problem with your browser.');
    }

    source = new EventSource("serverside.php");
    source.onopen = function (event) {
      console.log('streaming SSE opened');
    };

    source.onmessage = function(event) {
      console.log('Streaming Message Received');
      document.getElementById("result").innerHTML = event.data;
    };

    source.onerror = function (event) {
    console.log('ERROR EventSource');
  }
</script>

</body>
</html>

Если я проверю это, все будет в порядке. Я получил обновленное время в браузере, и когда я закрываю вкладку в своем браузере, Serverside.php не отправляет больше «Я здесь!» сообщение для входа. Это правильное поведение. Когда вкладка браузера закрыта, серверыide.php должны остановиться.

Но теперь, если я удалю или прокомментирую эти строки в файле serveride.php:

// echo 'data: ' . $time . "\n\n";
// flush();

Файл serveride.php остается таким:

<?php
  header('Content-Type: text/event-stream');
  header('Cache-Control: no-cache');
  ob_end_clean();

  while( true ) {
    set_time_limit(30);

    $time = date('d/m/Y H:i:s');

     //  echo 'data: ' . $time . "\n\n";
     //  flush();

    error_log('i am here!');
    sleep(1);
   }
?>

То есть никаких данных сброса вообще.

Если сейчас я загружу index.php, я ничего не получу от serveride.php. Но в этом случае, когда я закрываю вкладку браузера, Serverside.php продолжает работать и отправлять в журнал сообщения «Я здесь».

Кроме того, если серверыide.php отправляет данные и после отправки некоторых сообщений перестает отправлять больше данных, поведение остается тем же. Сообщения «Я здесь» продолжают поступать после закрытия вкладки.

  • Если я закрою вкладку браузера во время отправки данных с serveride.php, все будет нормально.
  • Если я закрою вкладку браузера после того, как данные были отправлены и ничего не отправлено с Serverside.php, Serverside.php продолжит работать.

Что это за объяснение?

Я полностью застрял.

1 Ответ

1 голос
/ 07 июня 2019

(Я предполагаю, что Apache - сервер, а вы используете mod_php, но основная идея должна быть одинаковой для любого веб-сервера.)

Если ваш PHP-скрипт никогда не выполняет flush(), содержимое буфера Apache будет отправлено клиенту (вашему браузеру) только тогда, когда буфер заполнится. И этого никогда не происходит, потому что ваш скрипт никогда не выполняет echo.

И Apache понимает, что клиент отключился, пытаясь отправить ему что-то в сокет и получить ошибку. И этого никогда не происходит, потому что вы никогда ничего не отправляете! (Да, чтобы понять, что сокет TCP / IP больше не работает, вы должны попытаться использовать его и потерпеть неудачу; нет простого состояния, на которое вы можете посмотреть.)

Лучшее из известных мне решений - заставить серверный сценарий отправить сообщение keep-alive. То есть пустое сообщение или временная метка каждые (например, 40 секунд). Если ваш подлинный поток данных затих, но вы отправляете подтверждение активности каждые 40 секунд, то ваше среднее время, чтобы заметить, что клиент отключился, составит 20 секунд.

(И это, безусловно, хорошая идея, особенно если клиенты часто подключаются и отключаются, так как в противном случае они фактически удерживают открытый сокет и процесс Apache.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...