SSE

คุณลักษณะนี้ต้องการ workerman>=4.0.0

SSE หรือ Server-sent Events เป็นเทคโนโลยีการส่งข้อมูลจากเซิร์ฟเวอร์ไปยังไคลเอนต์ ซึ่งมีหลักการ คือ หลังจากที่ไคลเอนต์ส่งคำขอ http ที่มีหัว Accept: text/event-stream การเชื่อมต่อจะไม่ถูกปิด และเซิร์ฟเวอร์จะสามารถส่งข้อมูลไปยังไคลเอนต์ได้อย่างต่อเนื่องบนการเชื่อมต่อนี้

ความแตกต่างของ 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
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);