SSE

이 기능은 workerman>=4.0.0이 필요합니다.

SSE는 Server-sent Events로, 서버에서 클라이언트로 데이터를 푸시하는 기술입니다. 본질적으로 클라이언트가 Accept: text/event-stream 헤드를 포함한 http 요청을 전송한 후 연결을 닫지 않으면, 서버는 이 연결을 통해 클라이언트에 계속 데이터를 푸시할 수 있습니다.

SSE와 websocket의 차이는 다음과 같습니다:

  • SSE는 서버가 클라이언트로만 데이터 전송 가능; Websocket은 양방향 통신을 지원합니다.
  • SSE는 기본적으로 끊어진 연결을 자동으로 재연결합니다; WebSocket은 사용자가 직접 구현해야 합니다.
  • SSE는 utf8 텍스트만 전송 가능하며, 이진 데이터는 utf8로 인코딩해야 전송됩니다; WebSocket은 기본적으로 utf8 및 이진 데이터 전송을 지원합니다.
  • SSE는 메시지 유형을 기본으로 제공하지만; WebSocket은 이를 사용자가 직접 구현해야 합니다.

예제

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\ServerSentEvents;
use Workerman\Protocols\Http\Response;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    // Accept 헤드가 text/event-stream이면 SSE 요청입니다.
    if ($request->header('accept') === 'text/event-stream') {
        // 먼저 Content-Type: text/event-stream 헤드를 포함한 응답을 보냅니다.
        $connection->send(new Response(200, ['Content-Type' => 'text/event-stream'], "\r\n"));
        // 클라이언트에 데이터를 주기적으로 푸시합니다.
        $timer_id = Timer::add(2, function () use ($connection, &$timer_id){
            // 연결이 닫힐 때는 타이머를 삭제하여 메모리 누수를 방지합니다.
            if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) {
                Timer::del($timer_id);
                return;
            }
            // message 이벤트를 전송하며, 이벤트에 포함된 데이터는 hello입니다. 메시지 id는 생략할 수 있습니다.
            $connection->send(new ServerSentEvents(['event' => 'message', 'data' => 'hello', 'id'=>1]));
        });
        return;
    }
    $connection->send('ok');
};

// 워커 실행
Worker::runAll();

클라이언트 javascript 코드

var source = new EventSource('http://127.0.0.1:8080');
source.addEventListener('message', function (event) {
  var data = event.data;
  console.log(data); // hello 출력
}, false);