热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HTML5如何支持服务器发送事件

HTML5如何支持服务器发送事件?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,

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: 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);
        }
    }

代码解释:
  把报头 "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\n
field可以取四个值:“data”, “event”, “id”, or “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浏览器监视视图:

响应报文头部:

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: ”,然后以“\n\n”结尾。

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

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

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

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

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

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

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

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

前端HTML5页面:

    
    
    
    
    

获取服务端更新数据

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}\n", retry);
            sb.AppendFormat("event:{0}\n", _event);
            sb.AppendFormat("id:{0}\n", id);
            sb.AppendFormat("data:{0}\n\n", data);            return sb.ToString();
        }
        
    }
}

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

HTML5如何支持服务器发送事件

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

HTML5如何支持服务器发送事件

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

HTML5如何支持服务器发送事件

至此,大功告成。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程笔记行业资讯频道,感谢您对编程笔记的支持。


推荐阅读
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • REST API 时代落幕,GraphQL 持续引领未来
    尽管REST API已广泛使用多年,但在深入了解GraphQL及其解决的核心问题后,我深感其将引领未来的API设计趋势。GraphQL不仅提高了数据查询的效率,还增强了灵活性和性能,有望成为API开发的新标准。 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 本文探讨了如何利用 jQuery 的 JSONP 技术实现跨域调用外部 Web 服务。通过详细解析 JSONP 的工作原理及其在 jQuery 中的应用,本文提供了实用的代码示例和最佳实践,帮助开发者解决跨域请求中的常见问题。 ... [详细]
  • 尽管我们尽最大努力,任何软件开发过程中都难免会出现缺陷。为了更有效地提升对支持部门的协助与支撑,本文探讨了多种策略和最佳实践,旨在通过改进沟通、增强培训和支持流程来减少这些缺陷的影响,并提高整体服务质量和客户满意度。 ... [详细]
  • TypeScript 实战分享:Google 工程师深度解析 TypeScript 开发经验与心得
    TypeScript 实战分享:Google 工程师深度解析 TypeScript 开发经验与心得 ... [详细]
  • HTML5大文件传输技术深度解析与实践分享
    本文深入探讨了HTML5在Web前端开发中实现大文件上传的技术细节与实践方法。通过实例分析,详细讲解了如何利用HTML5的相关特性高效、稳定地处理大文件传输问题,并提供了可供参考的代码示例和解决方案。此外,文章还讨论了常见的技术挑战及优化策略,旨在帮助开发者更好地理解和应用HTML5大文件上传技术。 ... [详细]
  • NoSQL数据库,即非关系型数据库,有时也被称作Not Only SQL,是一种区别于传统关系型数据库的管理系统。这类数据库设计用于处理大规模、高并发的数据存储与查询需求,特别适用于需要快速读写大量非结构化或半结构化数据的应用场景。NoSQL数据库通过牺牲部分一致性来换取更高的可扩展性和性能,支持分布式部署,能够有效应对互联网时代的海量数据挑战。 ... [详细]
  • 如何有效解决MySQL中预编译语句失效的问题及专业应对策略 ... [详细]
  • EMURGO Africa 与 Adaverse 合作投资 Momint,推动 Cardano NFT 生态系统在非洲市场的扩展 ... [详细]
  • 用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    HTTP协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的HTTP的网站是不 ... [详细]
  • 如何在服务器上配置SSL证书
    SSL证书是用于验证互联网上身份的一种数字凭证,通过启用HTTPS协议,确保用户与服务器之间的通信安全。本文将详细介绍如何在API和服务器上配置SSL证书,以提升网站的安全性和可信度。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 本文目录一览:1、php月薪多少合适2、php ... [详细]
author-avatar
Blackage
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有