0

0

HTML5支持服务器发送事件

大家讲道理

大家讲道理

发布时间:2017-05-28 10:54:23

|

2718人浏览过

|

来源于php中文网

原创

传统的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
    {        /// 
        /// ...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头信息如下:

极限网络办公Office Automation
极限网络办公Office Automation

专为中小型企业定制的网络办公软件,富有竞争力的十大特性: 1、独创 web服务器、数据库和应用程序全部自动傻瓜安装,建立企业信息中枢 只需3分钟。 2、客户机无需安装专用软件,使用浏览器即可实现全球办公。 3、集成Internet邮件管理组件,提供web方式的远程邮件服务。 4、集成语音会议组件,节省长途话费开支。 5、集成手机短信组件,重要信息可直接发送到员工手机。 6、集成网络硬

下载

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浏览器监视视图

响应报文头部:

响应报文内容:


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



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

获取服务端更新数据

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

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

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

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

 

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

至此,大功告成。

 

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

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

2

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

2

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

0

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

0

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.29

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

25

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

16

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

8

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

622

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 9.6万人学习

ASP 教程
ASP 教程

共34课时 | 4.2万人学习

Python 教程
Python 教程

共137课时 | 7.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号