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);