搜尋
首頁web前端H5教程HTML5支援伺服器發送事件

HTML5支援伺服器發送事件

May 28, 2017 am 10:54 AM
伺服器

傳統的WEB應用程式通訊時的簡單時序圖:

#現在Web App中,大都有Ajax,是這樣子:

 

HTML5有一個Server-Sent Events(SSE)功能,允許服務端推送資料到客戶端。 (通常叫資料推送)。基於資料推送是這樣的,當資料來源有新數據,它馬上發送到客戶端,不需要等待客戶端請求。這些新數據可能是最新聞,最新股票行情,來自朋友的聊天訊息,天氣預報等。

資料拉與推的功能是一樣的,使用者拿到新資料。但數據推送有一些優勢。 你可能聽過Comet, Ajax推送, 反向Ajax, HTTP流,WebSockets與SSE是不同的技術。可能最大的優勢是低延遲。 SSE用於web應用程式刷新數據,不需要使用者做任何動作。
     你可能聽過HTML5的WebSockets,也能推送資料到客戶端。 WebSockets是實現服務端更加複雜的技術,但它是真的全雙工socket, 服務端能推送資料到客戶端,客戶端也能推送資料回服務端。 SSE工作於存在HTTP/HTTPS協議,支援代理伺服器與認證技術。 SSE是文字協定你能輕易的調試它。如果你需要發送大部二進位資料從服務端到客戶端,WebSocket是更好的選擇。關於SSE與WebSocket的差別,本文下面會講到。

 

HTML5 伺服器發送事件(server-sent event)允許網頁獲得來自伺服器的更新
Server-Sent 事件- 單一向訊息傳遞
Server-Sent 事件指的是網頁自動取得來自伺服器的更新。
以前也可能做到這一點,前提是網頁必須詢問是否有可用的更新。透過伺服器發送事件,更新能夠自動到達。
範例:Facebook/Twitter 更新、估價更新、新的部落格文章、賽事結果等。

瀏覽器支援(所有主流瀏覽器均支援伺服器傳送事件,除了Internet Explorer。)

EventSource 推送(ajax普通輪詢):

處理過程:

客戶端建立EventSource物件,對伺服器透過http協定不斷進行請求。伺服器對客戶端的回應資料格式有四個部分構成,event,data,id,空格行。用戶端接收到伺服器端的回應資料之後,根據event事件值,找到EventSource物件對應的事件監聽器。

 

接收Server-Sent 事件通知
EventSource 物件用於接收伺服器傳送事件通知:


##

    //创建一个新的 EventSource 对象,规定发送更新的页面的 URL
    var source = new EventSource("../api/MyAPI/ServerSentEvents");    //默认支持message事件
    source.onmessage = function (event) {
        console.log(source.readyState);
        console.log(event);
    };


#實例解析:

  建立一個新的EventSource 對象,然後規定發送更新的頁面的URL(本例中是"demo_sse.php"),
參數url就是伺服器網址,必須與目前網頁的網址在同一個網域(domain),而且協定和連接埠都必須相同  每接收到一次更新,就會發生onmessage 事件

 

檢測Server-Sent 事件支援

以下實例,我們編寫了一段額外的程式碼來偵測伺服器傳送事件的瀏覽器支援情況:


if(!!EventSource && typeof(EventSource)!=="undefined")
{    // 浏览器支持 Server-Sent
    // 一些代码.....}else{    // 浏览器不支持 Server-Sent..}


#伺服器端程式碼實例

為了讓上面的範例可以運行,您還需要能夠發送資料更新的伺服器(例如PHP、
ASPASP.NET、Java)。 伺服器端事件流的語法是非常簡單的。你
需要把 "Content-Type" 標頭設定為 "text/event-stream"。現在,您可以開始發送事件流了。 我只會
C#,所以用ASP.NET的MVC 裡面的ApiController寫了個最簡單的伺服器端:


    public class MyAPIController : ApiController
    {        /// <summary>
        /// ...api/MyAPI/ServerSentEvents        /// </summary>
        /// <returns></returns>        [HttpGet, HttpPost]        public Task<httpresponsemessage> ServerSentEvents()
        {            //Response.ContentType = "text/event-stream"            //Response.Expires = -1            //Response.Write("data: " & now())            //Response.Flush()
            
            string data = "id: 123456\nevent: message\ndata: 666\n\n";

            HttpResponseMessage response = new HttpResponseMessage
            {                //注意:ContentType = "text/event-stream"
                Content = new StringContent(data, Encoding.GetEncoding("UTF-8"), "text/event-stream")
            };            return Task.FromResult(response);
        }
    }</httpresponsemessage>


程式碼解釋:
  把標頭"Content-Type" 設為"text/event-stream"
  規定不對頁面進行快取
#  輸出發送日期(始終以"data : " 開頭)
  向網頁刷新輸出資料

 


EventSource 物件

新產生的EventSource實例對象,有一個readyState屬性,表示連接所處的狀態

source.readyState
它可以取下列值:

  0,相當於常數EventSource.CONNECTING,表示連線尚未建立,或連接斷線。

  1,相當於常數EventSource.OPEN,表示連線已經建立,可以接受資料。

  2,相當於常數EventSource.CLOSED,表示連接已斷,且不會重連。

 


在上面的範例中,我們使用 onmessage 事件來取得訊息。不過還可以使用其他事件:
事件描述
onopen   當通往伺服器的連線被開啟
onmessage



## 當接收到訊息

onerror

  當發生錯誤
 

#open事件

連接一旦建立,就會觸發open事件,可以定義對應的

回呼函數



source.onopen = function(event) {
 // han
#dl
e open event

};

// 或


source.addEvent
List
ener("open", function(event) {
 // handle open event
}, false);
message事件

收到到數據就會觸發message事件。

source.onmessage = function(event) {

 var data = event.data;

 var origin = event.origin;

 var lastEventId = event.lastEventId;

# //// handle message

};

// 或


source.addEventListener("message", function(event) {

source.addEventListener("message", function(event) {

 var data = event.data;

 var origin = event.origin;

 var lastEventId = event.lastEventId;
 // handle message
}, false);
參數物件event有以下屬性:

#data:伺服器端傳回的資料(文字格式)。

origin: 伺服器端URL的網域部分,即協定、網域名稱和連接埠。

lastEventId:資料的編號,由伺服器端傳送。如果沒有編號,這個屬性為空。

error事件

如果發生通訊錯誤(例如連線中斷),就會觸發error事件。

source.onerror = function(event) {

 // handle error event

};

// 或者source.addEventListener("error" , function(event) {  // handle error event}, false);
自訂事件

伺服器可以與瀏覽器約定自訂事件。在這種情況下,發送回來的資料不會觸發message事件。

source.addEventListener("foo", function(event) {  var data = event.data;

 var origin = event.origin;

 var lastEventId = event.lastEventId;  // handle message}, false);上面程式碼表示,瀏覽器對foo事件進行監聽。
close方法close方法用於關閉連線。 source.close()
;資料格式概述
伺服器端所傳送的資料的

HTTP頭訊息

如下:

Content-Type: text/event-stream


##Cache

- Control: no-cache

######Connection: keep-alive#########後面的行都是以下格式:######field: value\n###field可以取四個值:“data”, “event”, “id”, 或 “retry”,也就是說有四類頭資訊。每次HTTP通訊可以包含這四類頭資訊中的一類或多類。 \n代表換行符號。 ######以冒號開頭的行,表示###註解###。通常,伺服器每隔一段時間就會向瀏覽器發送一個註釋,保持連線不中斷。 ######: This is a comment###下面是一些範例。 ######: this is a test stream\n\n######data: some text\n\n###

data: another message\n
data: with two lines \n\n
data:数据栏

数据内容用data表示,可以占用一行或多行。如果数据只有一行,则像下面这样,以“\n\n”结尾

data:  message\n\n
如果数据有多行,则最后一行用“\n\n”结尾,前面行都用“\n”结尾。

data: begin message\n
data: continue message\n\n
总之,最后一行的data,结尾要用两个换行符号,表示数据结束。

以发送JSON格式的数据为例。

data: {\n
data: "foo": "bar",\n
data: "baz", 555\n
data: }\n\n
id:数据标识符

数据标识符用id表示,相当于每一条数据的编号。

id: msg1\n
data: message\n\n
浏览器用lastEventId属性读取这个值。一旦连接断线,浏览器会发送一个HTTP头,里面包含一个特殊的“Last-Event-ID”头信息,将这个值发送回来,用来帮助服务器端重建连接。因此,这个头信息可以被视为一种同步机制。

event栏:自定义信息类型

event头信息表示自定义的数据类型,或者说数据的名字。

event: foo\n
data: a foo event\n\n

data: an unnamed event\n\n

event: bar\n
data: a bar event\n\n
上面的代码创造了三条信息。第一条是foo,触发浏览器端的foo事件;第二条未取名,表示默认类型,触发浏览器端的message事件;第三条是bar,触发浏览器端的bar事件。

retry:最大间隔时间

浏览器默认的是,如果服务器端三秒内没有发送任何信息,则开始重连。服务器端可以用retry头信息,指定通信的最大间隔时间。

retry: 10000\n

--------------------------------------------------------------------------------------

规范
Server-sent Events 规范是 HTML 5 规范的一个组成部分,具体的规范文档见参考资源。该规范比较简单,主要由两个部分组成:第一个部分是服务器端与浏览器端之间的通讯协议,第二部分则是在浏览器端可供 JavaScript 使用的 EventSource 对象。通讯协议是基于纯文本的简单协议服务器端的响应的内容类型是“text/event-stream”。响应文本的内容可以看成是一个事件流,由不同的事件所组成。每个事件由类型和数据两部分组成,同时每个事件可以有一个可选的标识符。不同事件的内容之间通过仅包含回车符和换行符的空行(“\r\n”)来分隔。每个事件的数据可能由多行组成。代码清单 1 给出了服务器端响应的示例:


retry: 10000\n
event: message\n
id: 636307190866448426\n
data: 2017/05/18 15:44:46\n\n


Chrome浏览器监视视图

响应报文头部:

响应报文内容:


每个事件之间通过空行来分隔。对于每一行来说,冒号(“:”)前面表示的是该行的类型,冒号后面则是对应的值。可能的类型包括:
类型为空白,表示该行是注释,会在处理时被忽略。
类型为 data,表示该行包含的是数据。以 data 开头的行可以出现多次。所有这些行都是该事件的数据。
类型为 event,表示该行用来声明事件的类型。浏览器在收到数据时,会产生对应类型的事件。
类型为 id,表示该行用来声明事件的标识符。
类型为 retry,表示该行用来声明浏览器在连接断开之后进行再次连接之前的等待时间。

当有多行数据时,实际的数据由每行数据以换行符连接而成。
如果服务器端返回的数据中包含了事件的标识符,浏览器会记录最近一次接收到的事件的标识符。如果与服务器端的连接中断,当浏览器端再次进行连接时,会通过 HTTP 头“Last-Event-ID”来声明最后一次接收到的事件的标识符。服务器端可以通过浏览器端发送的事件标识符来确定从哪个事件开始来继续连接。
对于服务器端返回的响应,浏览器端需要在 JavaScript 中使用 EventSource 对象来进行处理。EventSource 使用的是标准的事件监听器方式,只需要在对象上添加相应的事件处理方法即可。EventSource 提供了三个标准事件:

EventSource 对象提供的标准事件
名称   说明   事件处理方法
open   当成功与服务器建立连接时产生 onopen
message 当收到服务器发送的事件时产生 onmessage
error   当出现错误时产生 onerror

而且,服务器端可以返回自定义类型的事件。对于这些事件,可以使用 addEventListener 方法来添加相应的事件处理方法:


var es = new EventSource('events');
es.onmessage = function(e) {
    console.log(e.data);
};//自定义事件 myeventes.addEventListener('myevent', function(e) {
    console.log(e.data);
});


在指定 URL 创建出 EventSource 对象之后,可以通过 onmessage 和 addEventListener 方法来添加事件处理方法。当服务器端有新的事件产生,相应的事件处理方法会被调用。EventSource 对象的 onmessage 属性的作用类似于 addEventListener( ‘ message ’ ),不过 onmessage 属性只支持一个事件处理方法。

 

传统的网页都是浏览器向服务器“查询”数据,但是很多场合,最有效的方式是服务器向浏览器“发送”数据。比如,每当收到新的电子邮件,服务器就向浏览器发送一个“通知”,这要比浏览器按时向服务器查询(polling)更有效率。服务器发送事件(Server-Sent Events,简称SSE)就是为了解决这个问题,而提出的一种新API,部署在EventSource对象上。目前,除了IE,其他主流浏览器都支持。
简单说,所谓SSE,就是浏览器向服务器发送一个HTTP请求,然后服务器不断单向地向浏览器推送“信息”(message)。这种信息在格式上很简单,就是“信息”加上前缀“data: ”,然后以“\n\n”结尾。

SSE与WebSocket有相似功能,都是用来建立浏览器与服务器之间的通信渠道。两者的区别在于:

  WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。

  WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。

  SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。

  SSE默认支持断线重连,WebSocket则需要额外部署。

  SSE支持自定义发送的数据类型。

从上面的比较可以看出,两者各有特点,适合不同的场合。

 

个人完整的HTML5页面和C#(MVC实现服务端代码)如下:

前端HTML5页面:


nbsp;html>
    <meta>
    <title>HTML5 服务器发送事件(Server-Sent Events)-单向消息传递</title>
    <meta>
    <meta>
    <h1 id="获取服务端更新数据">获取服务端更新数据</h1>
    <p></p><script>if(typeof(EventSource)!=="undefined")
{    //创建一个新的 EventSource 对象,规定发送更新的页面的 URL
    var source = new EventSource("../api/MyAPI/ServerSentEvents");    //默认支持open事件    source.onopen = function (event) {
        console.log(source.readyState);
        console.log(event);
    };    //默认支持error事件    source.onerror = function (event) {
        console.log(source.readyState);
        console.log(event);
    };    //默认支持message事件    source.onmessage = function (event) {
        console.log(source.readyState);
        console.log(event);
        document.getElementById("result").innerHTML += event.data + "<br>";
    };    //处理服务器响应报文中的自定义事件    source.addEventListener("CustomEvent", function (e) {
        console.log("唤醒自定义事件");
        console.log(e);
        document.getElementById("result").innerHTML += e.data + "<br>";
    });
}else{
    document.getElementById("result").innerHTML="抱歉,你的浏览器不支持 server-sent 事件...";
}</script>


C#写的服务器端:


using System;using System.Net.Http;using System.Text;using System.Threading.Tasks;using System.Web.Http;namespace WebTest.Controllers
{    /// <summary>
    /// api/{controller}/{id}    /// </summary>
    public class MyAPIController : ApiController
    {        static readonly Random random = new Random();        /// <summary>
        /// ...api/MyAPI/ServerSentEvents        /// </summary>
        /// <returns></returns>        [HttpGet, HttpPost]        public Task<httpresponsemessage> ServerSentEvents()
        {            //Response.ContentType = "text/event-stream"            //Response.Expires = -1            //Response.Write("data: " & now())            //Response.Flush()
            
            string data = "";            if (random.Next(0, 10) % 3 == 0)
            {                //唤醒自定义的CustomEvent
                data = ServerSentEventData("这是自定义通知", DateTime.Now.Ticks.ToString(), "CustomEvent");
            }            else
            {                //唤醒默认的message
                data = ServerSentEventData(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), DateTime.Now.Ticks.ToString());
            }

            HttpResponseMessage response = new HttpResponseMessage
            {                //注意:ContentType = "text/event-stream"
                Content = new StringContent(data, Encoding.GetEncoding("UTF-8"), "text/event-stream")
            };            return Task.FromResult(response);
        }        public string ServerSentEventData(string data, string id, string _event = "message", long retry = 10000)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("retry:{0}\n", retry);
            sb.AppendFormat("event:{0}\n", _event);
            sb.AppendFormat("id:{0}\n", id);
            sb.AppendFormat("data:{0}\n\n", data);            return sb.ToString();
        }
        
    }
}</httpresponsemessage>


通信在页面上的显示结果:

通过Chrome监控网络交互时序:

通过Chrome浏览器控制台输出,下面是一轮ope、message、error事件的详情:

 

至此,大功告成。

 

以上是HTML5支援伺服器發送事件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
H5:網絡內容和設計的未來H5:網絡內容和設計的未來May 01, 2025 am 12:12 AM

H5(HTML5)將通過新元素和API提升網頁內容和設計。 1)H5增強了語義化標記和多媒體支持。 2)它引入了Canvas和SVG,豐富了網頁設計。 3)H5的工作原理是通過新標籤和API擴展HTML功能。 4)基本用法包括使用創建圖形,高級用法涉及WebStorageAPI。 5)開發者需注意瀏覽器兼容性和性能優化。

H5:網絡開發的新功能和功能H5:網絡開發的新功能和功能Apr 29, 2025 am 12:07 AM

H5帶來了多項新功能和能力,極大提升了網頁的互動性和開發效率。 1.語義化標籤如、增強了SEO。 2.多媒體支持通過和標籤簡化了音視頻播放。 3.Canvas繪圖提供了動態圖形繪製工具。 4.本地存儲通過localStorage和sessionStorage簡化了數據存儲。 5.地理位置API便於開發基於位置的服務。

H5:HTML5的關鍵改進H5:HTML5的關鍵改進Apr 28, 2025 am 12:26 AM

HTML5帶來了五個關鍵改進:1.語義化標籤提升了代碼清晰度和SEO效果;2.多媒體支持簡化了視頻和音頻嵌入;3.表單增強簡化了驗證;4.離線與本地存儲提高了用戶體驗;5.畫布與圖形功能增強了網頁的可視化效果。

HTML5:標準及其對Web開發的影響HTML5:標準及其對Web開發的影響Apr 27, 2025 am 12:12 AM

HTML5的核心特性包括語義化標籤、多媒體支持、離線存儲與本地存儲、表單增強。 1.語義化標籤如、等,提升代碼可讀性和SEO效果。 2.和標籤簡化多媒體嵌入。 3.離線存儲和本地存儲如ApplicationCache和LocalStorage,支持無網絡運行和數據存儲。 4.表單增強引入新輸入類型和驗證屬性,簡化處理和驗證。

H5代碼示例:實際應用和教程H5代碼示例:實際應用和教程Apr 25, 2025 am 12:10 AM

H5提供了多種新特性和功能,極大地增強了前端開發的能力。 1.多媒體支持:通過和元素嵌入媒體,無需插件。 2.畫布(Canvas):使用元素動態渲染2D圖形和動畫。 3.本地存儲:通過localStorage和sessionStorage實現數據持久化存儲,提升用戶體驗。

H5和HTML5之間的連接:相似性和差異H5和HTML5之間的連接:相似性和差異Apr 24, 2025 am 12:01 AM

H5和HTML5是不同的概念:HTML5是HTML的一個版本,包含新元素和API;H5是基於HTML5的移動應用開發框架。 HTML5通過瀏覽器解析和渲染代碼,H5應用則需要容器運行並通過JavaScript與原生代碼交互。

H5代碼的基礎:密鑰元素及其目的H5代碼的基礎:密鑰元素及其目的Apr 23, 2025 am 12:09 AM

HTML5的關鍵元素包括、、、、、等,用於構建現代網頁。 1.定義頭部內容,2.用於導航鏈接,3.表示獨立文章內容,4.組織頁面內容,5.展示側邊欄內容,6.定義頁腳,這些元素增強了網頁的結構和功能性。

HTML5和H5:了解常見用法HTML5和H5:了解常見用法Apr 22, 2025 am 12:01 AM

HTML5和H5沒有區別,H5是HTML5的簡稱。 1.HTML5是HTML的第五個版本,增強了網頁的多媒體和交互功能。 2.H5常用於指代基於HTML5的移動網頁或應用,適用於各種移動設備。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。