Как запускать события EventSource SSE?

Недавно я обнаружил EventSource, в YUI3 есть модуль галереи для нормализации и резервного поведения, это то, что я решил использовать в своем примере, поскольку я уже использую эту структуру.

Так что я довольно много искал, прочитал много блогов, сообщений и примеров, и все они показывают примерно одно и то же: как настроить основные события SSE. Теперь у меня есть 6 примеров срабатывания событий открытия/сообщения/ошибки/закрытия.

Чего у меня нет (что, как я надеялся, даст эта ссылка me) является примером того, как запускать события SSE, которые более полезны для моего приложения, я пробую событие под названием «обновление».

Вот моя основная тестовая страница: http://codefinger.co.nz/public/yui/eventsource/test.php (с тем же успехом это может быть html-файл, здесь пока нет php-кода)

А вот 'message.php' в конструкторе EventSource:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.

/**
 * Constructs the SSE data format and flushes that data to the client.
 *
 * @param string $id Timestamp/id of this connection.
 * @param string $msg Line of text that should be transmitted.
 */
function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}
while(true) {
  $serverTime = time();
  sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));
  sleep(10);
}

// I was hoping calling this file with a param might allow me to fire an event,
// which it does dutifully, but no browsers register the 'data : update' - though
// I do see the response in Firebug.
if( $_REQUEST['cmd'] ){
    sendMsg($serverTime, $_REQUEST['cmd'] );
}
?>

Из приведенного выше живого примера вы можете видеть, что я пытался использовать модуль ввода-вывода YUI для отправки запроса с параметром для запуска моего события «обновление», когда я нажимаю кнопку «обновить». Кажется, это работает, как вы можете видеть на панели сети Firebug, но мое событие не обрабатывается (я понимаю, что приведенный выше скрипт снова запустит этот цикл, я просто хочу, чтобы мое событие обрабатывалось в подключенных браузерах, затем я удалю /уборка).

Я делаю эту часть неправильно? Или есть что-то более фундаментальное, что я делаю неправильно? Я пытаюсь отправить события в ответ на изменение состояния моего пользовательского интерфейса.

Этот ТАК вопрос, казалось, был близок, @tomfumb прокомментировал, что его следующим вопросом будет «как отправлять новые события клиенту после установления первоначального соединения — теперь я вижу, что PHP просто должен никогда не прекращать выполнение». Но, конечно же, я бы отправлял события только тогда, когда они происходят... а не постоянно...


person danjah    schedule 05.03.2012    source источник


Ответы (1)


в вашем подходе есть несколько проблем:

  1. The server-side code that reads the cmd parameter is unreachable because of the infinite loop that sends event data to the client.
  2. You are trying to send an event from the client to the server. It is in the specification name - Server-Sent Events - the server is the sender and the client is the receiver of events. You have options here:
    1. Use the appropriate specification for the job called Web Sockets which is a two-way communication API
    2. Write the logic that makes the desired type of communication possible

Если вы решите остаться с SSE API, я вижу два возможных сценария.

  1. Reuse the same Event Source connection and store a pool of connections on the server. When the user sends subsequent XMLHttpRequest with the update command, get the EventSource connection from the pool, that was made by this visitor, and send response with it that specifies your custom event type, the default type is message. It is important to avoid entering in the infinite loop that would make another EventSource connection to the client, but the client does not handle it because he made the request with XMLHttpRequest and not with EventSource.
  2. Make all requests with EventSource. Before making a new EventSource request, close the previous one - you can do this from the client or from the server. On the server check the parameters and then send data to client.

Также вы можете использовать XMLHttpRequest с (длинным) опросом и, таким образом, избежать необходимости использования EventSource. Из-за простоты вашего примера я не вижу причин смешивать два типа запросов.

person Dimitar Bonev    schedule 10.03.2012
comment
Спасибо Димитар. Я думаю, что правильный инструмент для работы стал очень очевидным. За последнюю неделю я прочитал много документов и примеров и теперь понимаю, что ответом является двунаправленная связь на чем-то другом, кроме Apache. Обидно, у меня низкий опыт работы с серверными технологиями, PHP+Apache в целом дал мне все, что мне нужно, без головной боли. Я нашел мод Apache @ github: github.com/disconnect/apache-websocket/issues/ 9, но комментарий к коммуникациям пула соединений относится к части записи логики, которую вы предлагаете. Сейчас, похоже, я буду исследовать node.js. - person danjah; 11.03.2012
comment
@Danjah Вот хорошее сравнение между WS и SSE: stackoverflow.com/a/5326159/691308 - person Dimitar Bonev; 12.03.2012
comment
Эта страница html5rocks - это именно то, что я прочитал на прошлой неделе, я только хотел бы знать вещи, не проходя через боль проб и ошибок: P - person danjah; 12.03.2012