HTML5 Server-Sent Event
Bài đăng này đã không được cập nhật trong 3 năm
Giới thiệu
Chúng ta đã nghe nhiều về ứng dụng web real-time (như ứng dụng chat, game online,...), một trong những cách thức phổ biến được dùng đến đó là Web Socket. Bên cạnh đó các bạn cũng có thể đã nghe qua về các công nghệ khác như Ajax polling, Server-Sent events,...
Trong bài viết này, mình xin giới thiệu về HTML5 Server-Sent events.
HTML5 Server-Sent Events là gì?
HTML5 Server-Sent Events (SSE) hay còn được biết đến với tên gọi HTML5 Event Source là một Web Api cho phép kết nối thời gian thực giữa server và client (browser). Tuy nhiên, khác với WebSockets, SSE chỉ có 1 chiều dữ liệu, đó là từ server đến client (chỉ có server gửi dữ liệu đến client).
Tại sao dùng SSE khi đã có Web Sockets
Ưu điểm của SSE đó là API đơn giản, dễ thực hiện, không yêu cầu việc setup và implement phức tạp như Web sockets. SSE hoạt động với giao thức HTTP thông thường, không yêu cầu một Web socket server mới hay các giao thức đặc biệt khác.
Trong thực tế, không phải ứng dụng web real time nào cũng cần sự tương tác 2 chiều giữa client và server, trong trường hợp này việc sử dụng SSE là dễ dàng hơn rất nhiều. Có thể kế đến một số trường hợp như:
- Ứng dụng dashboard, đồ thị chart
- News feeds
- Ứng dụng theo dõi hoạt động của server
- Ứng dụng có dữ liệu thay đổi nhanh chóng như giá cả, thị trường, tình trạng hàng hóa, thông tin các trận đấu thể thao,...
Một ưu điểm nữa của SSE đó là, client có thể tự động kết nối lại server nếu bị mất kết nối, thời gian timeout trước khi client kết nối lại có thể tùy chỉnh được từ server. Khi thực hiện kết nối lại, client sẽ tự động gửi ID của event cuối cùng nó nhận được, nhờ đó server có thể biết được client đã bị bỏ qua bao nhiêu message để gửi lại những message đó.
SSE hoạt động với hầu hết các trình duyệt, ngoại trừ IE. Không biết trong tương lai IE có support hay nó có còn tồn tại hay không , tuy nhiên, chúng ta vẫn có thể sử dụng các polyfills để support đầy đủ tất cả các trình duyệt.
Cách thức hoạt động
Mô hình kết nối
p=. _^http://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet^_
SSE gồm 2 thành phần chính
-
Server side gửi dữ liệu dạng text UTF-8 đến client theo định dạng "Event stream" (MIME:
text/event-stream
).-
Định dạng event stream
Dạng đơn giản, response chỉ trả về dữ liệu (phần phía sau
data:
), kết thúc bằng 2 ký tự\n
. Client sẽ nhận event mặc định làmessage
, client lấy dữ liệu thông quaevent.data
data: a message\n\n
Dữ liệu dạng JSON
data: {"message": "JSON"}\n\n
Kèm theo message id, client lấy giá trị này thông qua
event.lastEventId
id: 1111\n data: a message\n\n
Kèm theo event name, eg:
custom-event
, client lắng nghe sự kiệncustom-event
data: Data of message event\n\n event: custom-event\n data: Data of custom-event\n\n
Các dòng bắt đầu với kí tự
:
được xem như comment: This is a comment data: a message\n\n
Kiểm soát thời gian timeout trước khi client thực hiện kết nối lại, ví dụ 10s
retry: 10000\n data: a message\n\n
-
Server example
Ví dụ đơn giản sử dụng PHP, lấy thông tin CPU usage của server gửi dữ liệu cho client mỗi 2s
<?php // Set necessary headers header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); require __DIR__ . '/vendor/autoload.php'; $linfo = new \Linfo\Linfo; $parser = $linfo->getParser(); // Using while to keep server connection open, so we have only one request. // If connection is closed browser will reconnect and will send last event Id. while (true) { $parser->determineCPUPercentage(); sendMessage($parser->getCPUUsage(), 'cpu', time()); sleep(2); } function sendMessage($value, $event = null, $id = null, $retry = null) { if ($retry) { echo "retry: $retry\n"; } if ($id) { echo "id: $id\n"; } if ($event) { echo "event: $event\n"; } echo "data: $value\n\n"; ob_flush(); flush(); }
Hoặc sử dụng libSSE-php
<?php require __DIR__ . '/vendor/autoload.php'; use Sse\Events\TimedEvent; use Sse\SSE; use Linfo\Linfo; class SysEvent extends TimedEvent { /** * the interval in seconds to get new data */ public $period = 1; private $linfo; public function __construct() { $this->linfo = new Linfo; } /** * Get updated data */ public function update() { $parser = $this->linfo->getParser(); $parser->determineCPUPercentage(); return $parser->getCPUUsage(); } } $sse = new SSE(); $sse->addEventListener('cpu', new SysEvent()); $sse->start();
-
-
Client side sử dụng EventSource interface để nhận dữ liệu từ server như các DOM events (ví dụ như onclick, onhover,...) thông thường khác.
var evtSource = new EventSource("/path/to/server-resource"); // Event khi clien connect thành công đến server evtSource.addEventListener('open', function(event) { console.log('Connection was opened'); }, false); // Khi có lỗi xảy ra (VD: connection closed) // Client tự động connect lại sau (mặc định) 3 giây evtSource.addEventListener('error', function(event) { if (event.eventPhase == EventSource.CLOSED) { console.log('> Connection was closed'); } }, false); // Event khi server gửi dữ liệu, tên event mặc định là message evtSource.addEventListener('message', function(event) { var data = event.data; // or JSON.parse(event.data) if json var dataId = event.lastEventId; // Id được gửi server. Khi kết nối lại, // client sẽ tự dộng gửi kèm trong header Last-Event-Id if (dataId == 'CLOSED') { // Ngăn client không kết nối lại server evtSource.close(); } }, false); // Custom event, server trả về sự kiện với tên: custom-event evtSource.addEventListener('custom-event', function(event) { var data = event.data; // ... }, false);
Demo
- Website: http://codedaily.info/sse/
- Github https://github.com/tuanpht/sse-demo
References
- https://www.w3.org/TR/eventsource/
- https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
- https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
- https://hpbn.co/server-sent-events-sse/
- https://www.html5rocks.com/en/tutorials/eventsource/basics/
- http://html5doctor.com/server-sent-events/
- http://streamdata.io/blog/server-sent-events/
- http://caniuse.com/#feat=eventsource
- http://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet
- https://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/
All rights reserved