Html5 服务端推送 Server-Sent Event

服务器推送事件(Server-sent Events)是 HTML 5 规范中的一个组成部分,可以用来从服务端实时推送数据到浏览器端。相对于与之类似的 COMET 和 WebSocket 技术来说,服务器推送事件的使用更简单,对服务器端的改动也比较小。对于某些类型的应用来说,服务器推送事件是最佳的选择。

  • WebSocket

    在介绍 HTML 5 服务器推送事件之前,首先介绍一些上面提到的几种服务器端数据推送技术。第一种是 WebSocket。WebSocket 规范是 HTML 5 中的一个重要组成部分,已经被很多主流浏览器所支持,也有不少基于 WebSocket 开发的应用。正如名称所表示的一样,WebSocket 使用的是套接字连接,基于 TCP 协议。使用 WebSocket 之后,实际上在服务器端和浏览器之间建立一个套接字连接,可以进行双向的数据传输。WebSocket 的功能是很强大的,使用起来也灵活,可以适用于不同的场景。不过 WebSocket 技术也比较复杂,包括服务器端和浏览器端的实现都不同于一般的 Web 应用。

  • 轮询

    除了 WebSocket 之外,其他的实现方式是基于 HTTP 协议来达到实时推送的效果。第一种做法是简易轮询,即浏览器端定时向服务器端发出请求,来查询是否有数据更新。这种做法比较简单,可以在一定程度上解决问题。不过对于轮询的时间间隔需要进行仔细考虑。轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担。

缺点:

1:轮询是由客户端发起的,那么在服务端就不能判别我要推送的内容是否已经过期,因为我很难判断某个信息是否已经推送给全部的客户端,那么服务端就需要缓存大量的数据。如果数据保存在数据库,那么还要每次请求都需要查询数据库,这对数据库和系统设计都是一个很大的挑战。

2:请求的频率太高,每次的请求包中含有同样的数据,这对pc来说也许算不得什么,但是对于移动客户端来讲,这应该不是最佳的方案。尤其是遇到还要做权限判断的时候,那么服务端的逻辑和效率也会造成用户体验的降低。

  • COMET

    COMET 技术改进了简易轮询的缺点,使用的是长轮询。长轮询的方式在每次请求时,服务器端会保持该连接在一段时间内处于打开状态,而不是在响应完成之后就立即关闭。这样做的好处是在连接处于打开状态的时间段内,服务器端产生的数据更新可以被及时地返回给浏览器。当上一个长连接关闭之后,浏览器会立即打开一个新的长连接来继续请求。不过 COMET 技术的实现在服务器端和浏览器端都需要第三方库的支持。

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

综合比较上面提到的 4 种不同的技术,简易轮询由于其本身的缺陷,并不推荐使用。COMET 技术并不是 HTML 5 标准的一部分,从兼容标准的角度出发,也不推荐使用。WebSocket 规范和服务器推送技术都是 HTML 5 标准的组成部分,在主流浏览器上都提供了原生的支持,是推荐使用的。不过 WebSocket 规范更加复杂一些,适用于需要进行复杂双向数据通讯的场景。对于简单的服务器数据推送的场景,使用服务器推送事件就足够了。

基于数据推送是这样的,当数据源有新数据,它马上发送到客户端,不需要等待客户端请求。这些新数据可能是最新闻,最新股票行情,来自朋友的聊天信息,天气预报等。

数据拉与推的功能是一样的,用户拿到新数据。但数据推送有一些优势。 你可能听说过Comet, Ajax推送, 反向Ajax, HTTP流,WebSockets与SSE是不同的技术。可能最大的优势是低延迟。SSE用于web应用程序刷新数据,不需要用户做任何动作。

WebSockets是实现服务端更加复杂的技术,但它是真的全双工socket, 服务端能推送数据到客户端,客户端也能推送数据回服务端。SSE工作于存在HTTP/HTTPS协议,支持代理服务器与认证技术。SSE是文本协议你能轻易的调试它。如果你需要发送大部二进制数据从服务端到客户端,WebSocket是更好的选择。

好在Html5为我们提供了一种方式: Server-Sent Events包含新的HTML元素EventSource和新的MIME类型 text/event-stream 来完成我的需要。

服务器发送事件API也就是EventSource接口,在你创建一个新的EventSource对象的同时,你可以指定一个接受事件的URI.例如:

var evtSource = new EventSource("ssedemo.php");
<!DOCTYPE html>
<html>
<head>
    <title>sever Sent Event实例1</title>
</head>
<body>
    <h2>sever Sent Event实例1</h2>
    <div id="result"></div>
    <script type="text/javascript">
        var result = document.getElementById(‘result‘);
        if (typeof (EventSource) !== ‘undefined‘) {
            //创建事件源
            var source = new EventSource(‘test.php‘);
            //监听事件源发送过来的数据
            source.onmessage = function(event){
                result.innerHTML +=event.data +‘<br>‘;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }
    </script>
</body>
</html>
<?php
    //指定发送事件流的MIME为text/event-stream
    header(‘Content-Type:text/event-stream‘);
    //不缓存服务端发送的数据
    header(‘Cache-Control:no-cache‘);
    //指定服务器发送的事件名
    echo "event:test\n\n";
    // 定义服务器向客户端发送的数据
    echo "data:服务器当前时间为:".date(‘Y-m-d H:i:s‘)."\n\n";
    //向客户端发送数据流
    flush();

 ?>
  • 把报头 “Content-Type” 设置为 “text/event-stream”
  • 规定不对页面进行缓存
  • 输出发送日期(始终以 “data: ” 开头)
  • 向网页刷新输出数据

也许大家应该注意到,就是php推送的信息一个使用了”\n\n”作为结束标志,经过测试,如果不以”\n\n”作为结束标志,那么客户端将不能接收到推送的值。还有需要特别声明一下:推送的信息格式必须为”data:内容\n\n“,否则。。。

事件流格式

事件流仅仅是一个简单的文本数据流,文本应该使用UTF- 8格式的编码.每条消息后面都由一个空行作为分隔符.以冒号开头的行为注释行,会被忽略.

每条消息是由多个字段组成的,每个字段由字段名,一个冒号,以及字段值组成.

字段

  • event

    事件类型.如果指定了该字段,则在客户端接收到该条消息时,会在当前的EventSource对象上触发一个事件,事件类型就是该字段的字段值,你可以使用addEventListener()方法在当前EventSource对象上监听任意类型的命名事件,如果该条消息没有event字段,则会触发onmessage属性上的事件处理函数.

  • data

    消息的数据字段.如果该条消息包含多个data字段,则客户端会用换行符把它们连接成一个字符串来作为字段值.

  • id

    事件ID,会成为当前EventSource对象的内部属性”最后一个事件ID”的属性值.

  • retry

    一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段值不是整数,则会被忽略.

    除了上面规定的字段名,其他所有的字段名都会被忽略. Chrome每隔3秒向客户端推送一次,而FF是每5秒推送一次。

注: 如果一行文本中不包含冒号,则整行文本会被解析成为字段名,其字段值为空.

EventSource 对象提供的标准事件

名称 说明 事件处理方法
open 当成功与服务器建立连接时产生 onopen
message 当收到服务器发送的事件时产生 onmessage
error 当出现错误时产生 onerror
<!DOCTYPE html>
<html>
<head>
    <title>sever Sent Event实例1</title>
</head>
<body>
    <h2>sever Sent Event实例1</h2>
    <button onclick="closeCnt()">断开连接</button>
    <div id="result"></div>
    <script type="text/javascript">
        var result = document.getElementById(‘result‘);
        if (typeof (EventSource) !== ‘undefined‘) {
            //创建事件源
            var source = new EventSource(‘test.php‘);
            //监听事件源发送过来的数据
            source.onmessage = function(event){
                result.innerHTML +=event.data +‘<br>‘;
            }

            source.onopen = connectionOpen;
            source.onclose = connectionClose;

            function connectionOpen(){
                if (source.readyState == 0) {
                    result.innerHTML +=‘未建立连接<br>‘;
                }
                if (source.readyState == 1) {
                    result.innerHTML +=‘连接成功<br>‘;
                }
            }

            function connectionClose(){
                result.innerHTML += "关闭连接,readyState属性值为:" + source.readyState + ‘<br>‘;
            }

            function closeCnt(){
                source.close();
                result.innerHTML += "断开连接,readyState属性值为:" + source.readyState + ‘<br>‘;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }
    </script>
</body>
</html>

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

<!DOCTYPE html>
<html>
<head>
    <title>sever Sent Event实例1</title>
</head>
<body>
    <h2>sever Sent Event实例1</h2>
    <div id="result"></div>
    <script type="text/javascript">
        var result = document.getElementById(‘result‘);
        if (typeof (EventSource) !== ‘undefined‘) {
            //创建事件源
            var source = new EventSource(‘test.php‘);
            //自定义事件源发送过来的数据,事件名和php中事件名对应
            source.addEventListener(‘myevent‘, ‘updateRequests‘, false);
            // source.onmessage = function() {
            //  result.innerHTML = event.data + ‘<br>‘;
            // }
            function updateRequests(event){
                result.innerHTML = event.data + ‘<br>‘;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }
    </script>
</body>
</html>
<?php
    //指定发送事件流的MIME为text/event-stream
    header(‘Content-Type:text/event-stream‘);
    //不缓存服务端发送的数据
    header(‘Cache-Control:no-cache‘);
    //指定服务器发送的事件名
    echo "event:myevent\n\n";
    // 定义服务器向客户端发送的数据
    echo "data:服务器当前时间为:".date(‘Y-m-d H:i:s‘)."\n\n";
    //向客户端发送数据流
    flush();

 ?>

前端是HTML5,后端可以是PHP, JSP, Node.js, Asp.net等应用。

时间: 2024-11-07 02:42:00

Html5 服务端推送 Server-Sent Event的相关文章

pushlet服务端推送——点对点单播(不用修改lib包)

pushlet点对点单播,在网上看 ,大家都是将包修改然后替换lib中class,其实不用不这么麻烦,java可以继承嘛,继承原来的类重写里面的方法就行,不必编译出来替换class,这样不方便修改 新建一个类,继承nl.justobjects.pushlet.core.SessionManager类,重写里面的createSession方法即可 package com.pushlet.serveToClient; import javax.servlet.http.HttpSession; im

pushlet服务端推送

---------------------在jsp页面中加入---------------------- <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <base href=

java SDK服务端推送 --极光推送(JPush)

网址:https://blog.csdn.net/duyusean/article/details/86581475 消息推送在APP应用中越来越普遍,来记录一下项目中用到的一种推送方式,对于Andriod它并没有自己的原生推送机制,一种简单的推送方式是采用第三方推送服务的方式,即通过嵌入SDK使用第三方提供的推送服务,主流的有百度云推送,极光推送,友盟,个推.亚马逊等等.本篇博文只介绍采用极光推送的方式.        如果你是一个新手,建议你先看完本篇博客,然后在去看官网,这样也许上手会快一

转:实现一个简单的服务端推送方案

原文来自于:http://blog.csdn.net/jiao_fuyou/article/details/17090355 客户端和服务端的交互有推和拉两种方式:如果是客户端拉的话,通常就是Polling:如果是服务端推的话,一般就是Comet,目前比较流行的Comet实现方式是Long Polling. 注:如果不清楚相关名词含义,可以参考:Browser 與 Server 持續同步的作法介紹. 先来看看Polling,它其实就是我们平常所说的轮询,大致如下所示: Polling 因为服务端

Java 消息推送------GoEasy实现服务端推送和web端推送

项目中需要消息推送,又想较低开发成本,具体需求:角色用户在后台管理页面发布一个消息,所有用这个系统的用户无论在哪个页面都能及时收到他发布的消息,后来我在网上查询到了一个第三方的免费推送服务-GoEasy push, 它可以满足我的需求,下面是如何用GoEasy进行信息推送及接收: 第一种:Java服务器端推送,web端接收推送信息 步骤: 从GoEasy官网下载jar包,并放到项目中. https://cdn.goeasy.io/sdk/goeasy-0.1.jar Java代码来了,你没有看错

使用AJAX技术发送异步请求,HTTP服务端推送

使用AJAX技术发送异步请求 什么是AJAX AJAX指一步Javascript和XML(Asynchronous JavaScript And XML),它是一些列技术的组合,简单来说AJAX基于XMLHttpRequest让我们在不重载页面的情况下和服务器进行数据交换. 加上JavaScript和DOM(Document Object Model,文档对象模型),我们就可以在接收到响应数据后局部更新页面.XML指的是数据的交互模式,可以是纯文本(Plain Text).HTML或JSON.

springboot 项目==基于websocket的服务端推送消息。

1.创建springboot项目,首先我们还是先引入依赖 <!-- webSocket begin--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- webSocket end--> 2.创建配置类 

其他技术---- 服务端推送SSE

SSE是Server-sent Events的简称,它是HTML5中的一种规范.目前为止那些老旧的浏览器是不直接支持SSE规范的,比如IE内核的浏览器. 我们知道websocket可以实现客户端与服务端的双向通信.SSE这个东西是可以实现服务端主动向客户端进行通信的,但是它仅仅是单向的.如果客户端与服务器端的数据交互不是特别频繁,那么我们是可以使用SSE技术来实现的. 协议 Server-sent Events主要由两部分组成. 1.服务器端与浏览器端之间的通讯协议 2.前端js对象EventS

HTTP/2之服务器推送(Server Push)最佳实践

商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处.   WeTest 导读 HTTP/1.X出色地满足互联网的普遍访问需求,但随着互联网的不断发展,其性能越来越成为瓶颈.IETF在2015年发布了HTTP/2标准, 着重于提高HTTP的访问体验, HTTP2优势主要包括: 二进制传输.头部压缩.多路复用和服务器推送(Server Push). 截止目前, 大部分CDN厂商已经宣布支持HTTP/2,然而"支持"大多省略了服务器推送(ServerPush)特性.估计这和ngin