HTML5支持服务器发送事件

传统的web应用程序通信时的简单时序图:

HTML5支持服务器发送事件

现在Web App中,大都有Ajax,是这样子:

HTML5支持服务器发送事件

 

立即学习“前端免费学习笔记(深入)”;

HTML5有一个Server-Sent Events(SSE)功能,允许服务端推送数据到客户端。(通常叫数据推送)。基于数据推送是这样的,当数据源有新数据,它马上发送到客户端,不需要等待客户端请求。这些新数据可能是最新闻,最新股票行情,来自朋友的聊天信息,天气预报等。

HTML5支持服务器发送事件

数据拉与推的功能是一样的,用户拿到新数据。但数据推送有一些优势。 你可能听说过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普通轮询):

HTML5支持服务器发送事件

处理过程:

客户端建立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、ASP、ASP.NET、Java)。
服务器端事件流的语法是非常简单的。你需要把 “Content-Type” 报头设置为 “text/event-stream”。现在,您可以开始发送事件流了。
我只会C#,所以用 ASP.NET的MVC 里面的ApiController写了个最简单的服务器端:

    public class MyAPIController : ApiController    {        ///         /// ...api/MyAPI/ServerSentEvents        ///         ///         [HttpGet, HttpPost]        public Task ServerSentEvents()        {            //Response.ContentType = "text/event-stream"            //Response.Expires = -1            //Response.Write("data: " & now())            //Response.Flush()                        string data = "id: 123456event: messagedata: 666";            HttpResponseMessage response = new HttpResponseMessage            {                //注意:ContentType = "text/event-stream"                Content = new StringContent(data, Encoding.GetEncoding("UTF-8"), "text/event-stream")            };            return Task.FromResult(response);        }    }

登录后复制

代码解释:
  把报头 “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) {
 // handle open event
};

// 或者

source.addEventListener(“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) {
 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
field可以取四个值:“data”, “event”, “id”, or “retry”,也就是说有四类头信息。每次HTTP通信可以包含这四类头信息中的一类或多类。代表换行符。

以冒号开头的行,表示注释。通常,服务器每隔一段时间就会向浏览器发送一个注释,保持连接不中断。

: This is a comment
下面是一些例子。

: this is a test stream

data: some text

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

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

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

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

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

data: {
data: “foo”: “bar”,
data: “baz”, 555
data: }
id:数据标识符

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

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

event栏:自定义信息类型

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

event: foo
data: a foo event

data: an unnamed event

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

retry:最大间隔时间

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

retry: 10000

————————————————————————————–

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

retry: 10000event: messageid: 636307190866448426data: 2017/05/18 15:44:46

登录后复制

Chrome浏览器监视视图:

响应报文头部:

HTML5支持服务器发送事件

响应报文内容:

HTML5支持服务器发送事件

每个事件之间通过空行来分隔。对于每一行来说,冒号(“:”)前面表示的是该行的类型,冒号后面则是对应的值。可能的类型包括:
类型为空白,表示该行是注释,会在处理时被忽略。
类型为 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: ”,然后以“”结尾。

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

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

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

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

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

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

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

 

立即学习“前端免费学习笔记(深入)”;

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

前端HTML5页面:

        HTML5 服务器发送事件(Server-Sent Events)-单向消息传递            

获取服务端更新数据

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 + "
"; }; //处理服务器响应报文中的自定义事件 source.addEventListener("CustomEvent", function (e) { console.log("唤醒自定义事件"); console.log(e); document.getElementById("result").innerHTML += e.data + "
"; });}else{ document.getElementById("result").innerHTML="抱歉,你的浏览器不支持 server-sent 事件...";}

登录后复制

C#写的服务器端:

using System;using System.Net.Http;using System.Text;using System.Threading.Tasks;using System.Web.Http;namespace WebTest.Controllers{    ///     /// api/{controller}/{id}    ///     public class MyAPIController : ApiController    {        static readonly Random random = new Random();        ///         /// ...api/MyAPI/ServerSentEvents        ///         ///         [HttpGet, HttpPost]        public Task 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}", retry);            sb.AppendFormat("event:{0}", _event);            sb.AppendFormat("id:{0}", id);            sb.AppendFormat("data:{0}", data);            return sb.ToString();        }            }}

登录后复制

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

HTML5支持服务器发送事件

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

HTML5支持服务器发送事件

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

HTML5支持服务器发送事件

 

立即学习“前端免费学习笔记(深入)”;

至此,大功告成。

 

立即学习“前端免费学习笔记(深入)”;

以上就是HTML5支持服务器发送事件的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2911868.html

(0)
上一篇 2025年3月11日 04:59:28
下一篇 2025年3月11日 04:59:37

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 将数据库从服务器移到浏览器–indexedDB基本操作封装

      数据库是属于服务器的,这是天经地义的事,但是有时候数据也许并非需要存储在服务器,但是这些数据也是一条一条的记录,怎么办?今天来带领你领略一下h5的一个新特性–indexeddb的风骚。你会情不自禁的发出感叹–不可…

    2025年3月11日 编程技术
    200
  • 分析和修复服务器内部错误:HTTP状态码500

    HTTP状态码500:分析服务器内部错误及其修复方案 摘要:HTTP状态码500表示服务器内部错误,是客户端向服务器发送请求时,服务器遇到了无法处理的错误而无法完成请求。本文将分析导致服务器内部错误的可能原因,并提出相应的修复方案。 一、引…

    2025年3月9日
    200
  • cookie保存之谜揭晓:详解浏览器与服务器之间的交互

    随着互联网的发展,我们越来越多地使用浏览器进行网页浏览、购物、登录等操作。而在这些过程中,我们时常听到一个词语——cookie。那么cookie到底是什么?它的作用又是什么?今天我们就来揭秘cookie的保存之谜,详细解析浏览器与服务器之间…

    2025年3月9日
    200
  • uploader秒传图片到服务器

    本文主要为大家详细介绍了uploader秒传图片到服务器的完整代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能帮助到大家。 先看看效果图: 页面中js部分 var f1 = null; var picarr = new Arr…

    2025年3月8日 编程技术
    200
  • 本地搭建微信小程序服务器如何实现

    本文主要介绍了本地搭建微信小程序服务器的实现方法的相关资料,希望通过本文能帮助到大家,让大家轻松的搭建自己的微信小程序的服务器,需要的朋友可以参考下,希望能帮助到大家。 本地搭建微信小程序服务器的实现方法 现在开发需要购买服务器,价格还是有…

    2025年3月8日 编程技术
    200
  • 实现react服务器渲染基础方法

    本文主要和大家介绍从零开始最小实现react服务器渲染详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。 前言 最近在写 koa 的时候想到,如果我部分代码提供api,部分代码支持ssr,那…

    2025年3月8日
    200
  • Webpack服务器端代码打包实例详解

    环境变量 之前,我们在项目里会经常使用 process.env.NODE_ENV, 但这个变量对于 webpack打包是有影响的, 在 production 的时候是有优化的.本文主要和大家介绍Webpack 服务器端代码打包的示例代码,小…

    编程技术 2025年3月8日
    200
  • js高效率服务器时间同步实例

    本文主要和大家分享一个js倒计时的功能代码,首先说一下,为什么要服务器时间同步, 因为服务器时间和本地电脑时间存在一定的时间差。有些对时效性要求非常高的应用,例如时时彩开奖,是不能容忍这种时间差存在的。 方案1:每次倒计时去服务端请求时间 …

    编程技术 2025年3月8日
    200
  • node静态文件服务器实例详解

    本文主要和大家介绍了实战node静态文件服务器的示例,本文首先会列出它的功能然后再以代码的形式分享给大家,希望能帮助到大家。 支持功能: 读取静态文件 访问目录可以自动寻找下面的index.html文件, 如果没有index.html则列出…

    编程技术 2025年3月8日
    200
  • 怎样用nodejs搭建服务器

    这次给大家带来怎样用nodejs搭建服务器,用nodejs搭建服务器的注意事项有哪些,下面就是实战案例,一起来看一下。 【创想鸟】相关教程推荐:Node.js视频教程 简单开始 1.安装node。https://nodejs.org/en/…

    2025年3月8日 编程技术
    200

发表回复

登录后才能评论