HTML5 SSE 瀏覽器發送事件
在遠古時代,網頁大都是靜態展示,服務器無需處理復雜且過多的請求,只需要靜靜地等待客戶端的請求,將 HTML 代碼通過 HTTP 的方式返回給客戶端。因此服務器也沒有主動推送數據給客戶端的能力,畢竟 HTTP 是無狀態的協議,即開即用。
后來隨著互聯網的發展,服務端有一些即時消息需要立即展示給客戶端,早期的處理方式是通過客戶端定時發起 HTTP 請求,這種方式命中率較低且浪費服務端資源?,F在有了 HTML5 之后不需要那么麻煩了,可以使用 websocket 或者 SSE。SSE 全稱 server-sent events 單項消息傳遞事件,相對于 websocket 這種雙向協議,SSE 較為輕量,它只支持服務端向客戶端推送消息。
1. 使用方式
1.1 創建實例
通過新建一個 sse 對象可以創建一個 SSE 實例,但是不要忘記檢測瀏覽器的支持情況:
if(typeof(EventSource)!=="undefined"){
var source = new EventSource("http://127.0.0.1/test.php");
}
上述示例實現了一個創建 SSE 對象的功能,創建之前需要檢測是否支持,目前 IE 之外的大部分瀏覽器都支持 SSE。sse 對象只有一個初始化參數,用于指定服務器的 url。
1.2 接收消息
創建實例成功之后,通過監聽 message 事件來實時獲取服務端的消息:
source.onmessage = function (event){
//處理業務請求
console.log(event.data)
}
1.3 服務端支持
服務器端需要對客戶端發起的 HTTP 請求做相應的回復,主要是將 HTTP 報文頭的 content-type 字段設置成 text/event-stream,下邊以 PHP 舉例:
header('content-type:text/event-stream');
while(true){
sleep(30000);
echo "message:".time();
//每隔半分鐘返回一個時間戳
}
1.4 其他事件
除了監聽 message 事件用于獲取服務端的數據之外,還有 open 事件用于監聽連接打開的狀態, error 事件用于監聽錯誤信息。
2. 幾種常用的客戶端-服務器消息傳遞方式
- http 最常用的協議,用于客戶端主動向服務器發送請求,單向傳遞;
- ajax HTTP 的擴展版,底層還是 HTTP 協議,只不過客戶端是無刷新的;
- comet 也是基于 HTTP 封裝的,使用 HTTP 長連接的方式,原理大致是將 HTTP 的timeout 設置較長,服務器有數據變化時返回數據給客戶端,同時斷開連接,客戶端處理完數據之后重新創建一個 HTTP 長連接,循環上述操作(這只是其中一種實現方式);
- websocket 這是 HTML5 中的新標準,基于 socket 的方式實現客戶端與服務端雙向通信,需要瀏覽器支持 HTML5;
- Adobe Flash Socket 這個也是使用 socket 的方式,需要瀏覽器支持 flash 才行,為了兼容老版本的瀏覽器;
- ActiveX object 只適用于 IE 瀏覽器;
目前尚沒有一種方式能兼容所有的瀏覽器,只能針對軟件的目標客戶人群做一定的兼容。 - sse 服務端單向推送。
3. 適用場景
并非所有場景都適合使用 sse 處理,在消息推送接收不頻繁的情況下選用 ajax 輪詢或者 sse 或者 websocket 其實差別不太大。sse 應該適用于服務端向客戶端發送消息頻繁而客戶端幾乎無需向服務端發送數據的場景下,例如:
- 新郵件通知;
- 訂閱新聞通知;
- 天氣變化;
- 服務器異常通知;
- 網站公告;
- 等等。
sse 的優缺點:
- SSE 使用 HTTP 協議,除 IE 外的大部分瀏覽器都支持;
- SSE 屬于輕量級,使用簡單;
- SSE 默認支持斷線重連;
- SSE 一般只用來傳送文本,二進制數據需要編碼后傳送;
- SSE 支持自定義發送的消息類型。
4. 總結
本章介紹了 websocket 的輕量級版本 sse 協議,簡述了 sse 協議的使用方法,對比了其他網頁中常用的消息推送方式以及他們的優缺點,這些協議涵蓋了大部分的使用場景,選用適合的協議類型可以避免不必要的資源和性能消耗。