服务器实时通知客户端方案,服务器发送/推送事件方案(2)server event,典型例子,可以用作股票、新闻信息推送
2016-11-14 15:59
981 查看
server event是html5规范的一部分,它相比websocket使用起来更简单,对服务器的改动也最小
前端html部分
服务器部分,其中最主要的是
①将返回的消息头的content_type设置为text/event-stream;
②返回的格式要以“data:”开头,前端收到后也是取event.data来得到信息;
③再就是返回需要加上两个换行。否则收不到MessageEvent的返回。
如果直接用spring 的controller返回值的的情况,会产生直接访问content_type消息头依然为text/html的情况,但是前端如果是使用的server event请求依然会得到text/stream的返回,因而不影响使用
以上的介绍,大家对server event已经基本了解,并可以测试例子,的确实现了服务器往客户端推送不断消息。但其实这个经常被引用的例子在不断的建立和断开链接,成了类似前端轮询那样的机制,容易误导大家。
下面的例子是一直在连接的情况下不断的推送要描绘的位置信息,更典型也更易于理解server event的设计意图
前端页面
或者用canvas绘制
bingo
前端html部分
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <div id="result"></div> <script> if(typeof(EventSource)!=="undefined") { var source=new EventSource("doevent"); //打开连接 source.onopen=function(event) { console.log("onopen",event); }; //错误信息 source.onerror=function(e) { console.log("err",e); }; //处理接受到的消息 source.onmessage=function(event) { console.log("onmessage",event); document.getElementById("result").innerHTML+=event.data + "<br />"; }; } else { document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events..."; } </script> </body> </html>
服务器部分,其中最主要的是
①将返回的消息头的content_type设置为text/event-stream;
②返回的格式要以“data:”开头,前端收到后也是取event.data来得到信息;
③再就是返回需要加上两个换行。否则收不到MessageEvent的返回。
@RequestMapping("/doEvent") void doEvent(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/event-stream"); resp.setHeader("expires", "-1"); resp.setHeader("cache-control", "no-cache"); String s = "data:"+new Date().toString()+"\n\n"; resp.getOutputStream().write(s.getBytes()); }
如果直接用spring 的controller返回值的的情况,会产生直接访问content_type消息头依然为text/html的情况,但是前端如果是使用的server event请求依然会得到text/stream的返回,因而不影响使用
@RequestMapping("/doevent") @ResponseBody String doEvent(HttpServletRequest req, HttpServletResponse rsp){ rsp.setContentType("text/event-stream"); return "data:"+new Date().toString()+"\n\n"; }
以上的介绍,大家对server event已经基本了解,并可以测试例子,的确实现了服务器往客户端推送不断消息。但其实这个经常被引用的例子在不断的建立和断开链接,成了类似前端轮询那样的机制,容易误导大家。
下面的例子是一直在连接的情况下不断的推送要描绘的位置信息,更典型也更易于理解server event的设计意图
@RequestMapping("/doevent") void doEvent(HttpServletRequest req, HttpServletResponse resp) { HttpHeadTool.allowAccess(resp); LogCore.BASE.info("{} doevent", req.getSession().getId()); resp.setContentType("text/event-stream"); resp.setHeader("expires", "-1"); resp.setHeader("cache-control", "no-cache"); int i = 0; int r = 100; //半径 int v = 50; //走一圈的步数 while(true){ i = (i+1)%(v*2); if(i==0){ r += 20; } double angel = i*Math.PI/v; //i 从 0到2π int x = (int)Math.round( r* Math.cos(angel) ); int y = (int)Math.round( r* Math.sin(angel) ); String s = "data:"+x+","+y+"\n\n"; try { resp.getOutputStream().write(s.getBytes()); } catch (Exception e) { LogCore.BASE.error(e.getMessage()); return; } try { resp.flushBuffer();//前端页面关闭或刷新 } catch (IOException e) { LogCore.BASE.error(e.getMessage()); return; } try { Thread.sleep(200); } catch (InterruptedException e) { LogCore.BASE.error(e.getMessage()); return; } } }
前端页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <div id="result"></div> <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <style type="text/css"> #box-container { position: relative; width : 800px; height : 600px; } #box { width : 40px; height : 40px; background-color : #f00; position : absolute; } #_lable { width : 20px; height : 20px; background-color : #00f; position : absolute; } #_origin { width : 5px; height : 5px; background-color : #00f; position : absolute; } </style> </head> <body> <div class="row-fluid"> <div class="row10 offset2"> <div class="page-header"> <h1>Random Movement<small> HTML 5 server sent events sample</small></h1> </div> </div> <div id="box-container" class="row10 offset2"> <div id="box"></div> <div id="_lable"></div> <div id="_origin"></div> </div> </div> <script> if(typeof(EventSource)!=="undefined") { var source=new EventSource("http://localhost:8084/doevent"); //打开连接 source.onopen=function(event) { console.log("onopen",event); }; //错误信息 source.onerror=function(e) { console.log("err",e); }; //处理接受到的消息 source.onmessage=function(event) { console.log("onmessage",event); document.getElementById("result").innerHTML=event.data + "<br />"; document.getElementById("_lable").innerHTML=event.data + "<br />"; var pos = event.data.split(','); x = pos[0]; y = pos[1]; o_x = Number(document.body.clientWidth)/2; o_y = Number(document.body.clientHeight)/2; x = Number(x) + Number(o_x); y = Number(y) + Number(o_y); $('#box').css({ left : x + 'px', top : y + 'px' }); $('#_lable').css({ left : x + 'px', top : y + 'px' }); $('#_origin').css({ left : o_x + 'px', top : o_y + 'px' }); }; } else { document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events..."; } </script> </body> </html>
或者用canvas绘制
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <div id="result"></div> <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <body> <canvas class="canvas" id ="canvas" style="background-color: red"> </canvas> <script> var canvas = document.getElementById("canvas"); canvas.width = document.body.scrollWidth; canvas.height = document.body.scrollHeight; if(typeof(EventSource)!=="undefined") { var source=new EventSource("http://localhost:8084/doevent"); //打开连接 source.onopen=function(event) { console.log("onopen",event); }; //错误信息 source.onerror=function(e) { console.log("err",e); }; //处理接受到的消息 source.onmessage=function(event) { console.log("onmessage",event); document.getElementById("result").innerHTML=event.data + "<br />"; var pos = event.data.split(','); x = pos[0]; y = pos[1]; o_x = Number(document.getElementById("canvas").clientWidth)/2; o_y = Number(document.getElementById("canvas").clientHeight)/2; x = Number(x) + Number(o_x); y = Number(y) + Number(o_y); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.arc(x, y, 5, 0, 2 * Math.PI, false); ctx.stroke(); }; } else { document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events..."; } </script> </body> </html>
bingo
相关文章推荐
- 服务器实时通知客户端方案,服务器发送/推送事件方案(1)websocket
- 修改例子,TCP服务器和客户端,加入线程的概念,实现单方多次发送信息
- server-sent-event使用流信息向客户端发送数据
- HTML5支持服务器发送事件(Server-Sent Events)-单向消息传递数据推送(C#示例)
- 基于 WEB 的实时事件通知方式 服务器推送
- EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新
- HTML5 Server-sent Events ASP.NET向Web客户端推送信息
- .net remoting 客户端与服务端绑定事件,一部电脑当服务器,另一部当客户端,发布后没法接收远程错误信息。
- 基于WEB 的实时事件通知方案
- 客户端遍历服务器的信息(比如滤镜效果显示新闻)
- 使用WCF实现服务器向客户端的信息推送
- 基于WEB 的实时事件通知方案
- qt fortuneserver 例子学习 ( 给客户端发送消息)
- ServerSocket和Socket建立通信(客户端发送消息服务器接收输出)
- HTML5 服务器推送事件(Server-sent Events)
- 局域网聊天工具(多线程),支持客户端与客户端间通信,服务器负责信息的接收与发送
- 基于WEB 的实时事件通知方案
- ServerSocket的一个简单例子,学习backlog参数的设置,即可以接受客户端的数量
- 为什么ServerSocket接收不到客户端Socket发送的信息?