【實作 Server 端

所謂 Server-Sent Event 中文解釋為伺服器推送或伺服器推播,主要是用來將伺服器上的資料自動傳輸至 Client 端,使用的是 HTTP 通訊協定。首先需要 Server 端的應用程式,筆者以 ASP.NET 泛型處理常式來實作本文 Server 端的應用程式,您也可以利用 PHP、JSP 等其他 Server 端的程式語言來實作。

Server 端的程式推送給 Client 端的封包是由 event(事件或識別名稱,預設值為 message)、data(要傳送給 Client 端的資料內容)、id(Server 端推送資料到 Client 端時的事件ID) 和 retry(以毫秒為單位,用來定義兩次要求之間的間隔時間)等四個欄位所組成,其格式為【欄位名稱:欄位內容】。其中又以 data 欄位最為重要,若 Server 端沒有傳送該欄位給 Client 端,即便您定義了資料接收的事件,該事件仍不會被觸發。

下列程式碼用來示範將回傳目前 Server 端的系統時間給 Client 端的瀏覽器,其中 ContentType 必須要設定為【text/event-stream】整個 Server-Sent Events 機制才能正常運作。

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Web;
05  
06 namespace ServerSendEvents
07 {
08     /// <summary>
09     /// ServerSide 的摘要描述
10     /// </summary>
11     public class ServerSide : IHttpHandler
12     {
13  
14         public void ProcessRequest(HttpContext context)
15         {
16             context.Response.ContentType = "text/event-stream";
17             context.Response.Write(string.Format("data:{0}\n", DateTime.Now.ToString()));
18         }
19  
20         public bool IsReusable
21         {
22             get
23             {
24                 return false;
25             }
26         }
27     }
28 }

實作 Client 端

Client 端要能接收 Server 端的推送資料,必須先建立 EventSource 物件,例如下列的程式碼,透過建構式傳入的 URL 來設定要從哪裡接收資料,接著 EventSource 物件便會以非同步方式來向 URL 參數所對應的 Server 端提出要求,以接收回傳的資料。

1 var es = new EventSource(url);

處理 Server 端推送下來的資料時,有三個事件屬性可以使用,分別是 onopen(連線建立時觸發)、onmessage(接收到 Server 端推送的訊息時觸發) 與 onerror(連線失敗時觸發)。

01 var es = new EventSource("ServerSide.ashx");
02 var stat;
03  
04 es.onerror = function (e) {
05     switch (e.target.readyState) {
06         case EventSource.CONNECTING:
07             stat = "等待重新連線";
08             break;
09         case EventSource.CLOSED:
10             stat = "連線失敗,停止連線";
11             break;
12     }
13     document.getElementById("divMsg").innerHTML += stat + "<br/>";
14 }
15  
16 es.onmessage = function (e) {
17     document.getElementById("divMsg").innerHTML += "現在時刻:" + e.data.toString() + "<br/>";
18 }
19  
20 es.onopen = function (e) {
21     switch (e.target.readyState)
22     {
23         case EventSource.CONNECTING:
24             stat = "Connecting";
25             break;
26         case EventSource.OPEN:
27             stat = "Open";
28             break;
29         case EventSource.CLOSED:
30             stat = "Closed";
31             break;
32         default:
33             stat = "n/a";
34             break;
35     }
36     document.getElementById("divMsg").innerHTML += "連線狀態:" + stat + "<br/>"
37 }

執行結果如下:

SNAGHTMLd4a92e

若您希望與 Server 端停止連線,可以呼叫 EventSource 的 Close 方法,例如下列的程式碼(其中 es 為上面所宣告的 EventSource 物件):

1 function Stop()
2 {
3     es.close();
4 }

變更重新連線的間隔時間

由上一節的執行結果可知,預設 Server 端每 5000 毫秒推送一次資料到 Client 端的瀏覽器上,若您要調整這個間隔時間,可以在 Server 端設定 retry 欄位的值,例如下列的程式碼:

1 context.Response.Write(string.Format("retry:{0}\n", "1000"));

修改過後重新執行 Client 端網頁,您將看到如下圖的結果,已經由原本的每 5000 毫秒推送一次,變成每 1000 毫秒推送一次。

SNAGHTMLe023f8

Felix 發表在 痞客邦 PIXNET 留言(0) 人氣()