在咱们平常开发中,会遇到服务端和客户端的通信,今天咱们就来比较一下HTML5新特性SSE和WebSocket的用法。web
SSE(Server-Sent Events,服务器发送事件)是围绕只读Comet 交互推出的API 或者模式。
SSE API容许网页得到来自服务器的更新(HTML5),用于建立到服务器的单向链接,服务器经过这个链接能够发送任意数量的数据。服务器响应的MIME类型必须是text/event-stream,并且是浏览器中的JavaScript API 能解析格式输出。SSE 支持短轮询、长轮询和HTTP 流,并且能在断开链接时自动肯定什么时候从新链接。浏览器
//判断是否支持SSE if('EventSource' in window){ //初始化SSE var url="http:localhost:8080/test/push"; var source=new EventSource(url); //开启时调用 source.onopen=(event)=>{ console.log("开启SSE"); } //监听message事件 source.onmessage=(event)=>{ var data=event.data; $("body").append($("<p>").text(data)); } //监听like事件 source.addEventListener('like',function(event){ var data=event.data; $("body").append($("<p>").text(data)); },false); //发生异常时调用 source.onerror=(event)=>{ console.log(event); }
客户端只须要直接使用**window.EventSource**对象,而后调用该对象的相应方法便可。安全
/** * SSE后台controller * @author like * */ @Controller @RequestMapping(value="/test") public class TestSSEController { @ResponseBody @RequestMapping(value="/push",produces="text/event-stream;charset=UTF-8") public String push(HttpServletResponse res){ res.setHeader("Access-Control-Allow-Origin","*"); Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-dd HH:mm:ss"); String nowDate=sdf.format(date); return "data: 我是一个data 如今时间是"+nowDate+" \nevent:like\n retry:5000\n\n"; } }
因为SSE是http请求,可是又限定是一个长链接,因此要设置MIME类型为text/event-stream。返回的为字符串。服务器
服务器向浏览器发送的 SSE 数据,必须是 UTF-8 编码的文本;websocket
每一次发送的信息,由若干个message组成,每一个message之间用\n\n分隔。每一个message内部由若干行组成;session
格式app
[field]:value\n
其中field能够为四种dom
data表明数据,event表明事件名称,id表明id,retry表明多少时间轮训一次。socket
因此个人服务端写的消息就能够翻译为:事件名称为**like**,数据为**我是一个data 如今时间是+当前时间**,每5秒轮训一次this
data: 我是一个data 如今时间是"+nowDate+" \nevent:like\n retry:5000\n\n
下面是接收消息:
WebSocket是HTML5开始提供的一种在单个 TCP 链接上进行全双工通信的协议。
var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8080/WebSocketTest/websocket"); } else { alert('当前浏览器 Not support websocket') } //链接发生错误的回调方法 websocket.onerror = function () { setMessageInnerHTML("WebSocket链接发生错误"); }; //链接成功创建的回调方法 websocket.onopen = function () { setMessageInnerHTML("WebSocket链接成功"); } //接收到消息的回调方法 websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //链接关闭的回调方法 websocket.onclose = function () { setMessageInnerHTML("WebSocket链接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket链接,防止链接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () { closeWebSocket(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭WebSocket链接 function closeWebSocket() { websocket.close(); } //发送消息 function send() { var message = document.getElementById('text').value; websocket.send(message); }
能够看到客户端直接调用ws地址就能够了。
/** * websocket服务 * @author like * */ @ServerEndpoint("/websocket") public class WebsocketTest { private static int onlineCount=0;//记录当前在线人数 //确保线程安全 private static CopyOnWriteArraySet<WebsocketTest> webSocketSet=new CopyOnWriteArraySet<WebsocketTest>(); private Session session; @OnOpen public void onOpen(Session session){ this.session=session; webSocketSet.add(this); addOnlineCount(); System.out.println("有新链接加入!当前在线人数为" + getOnlineCount()); } @OnClose public void OnClose(){ webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一链接关闭!当前在线人数为" + getOnlineCount()); } @OnMessage public void OnMessage(String message, Session session){ System.out.println("来自客户端的消息:" + message); //群发消息 for(WebsocketTest item: webSocketSet){ try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } } } @OnError public void OnError(Session session, Throwable error){ System.out.println("发生错误"); error.printStackTrace(); } public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebsocketTest.onlineCount++; } public static synchronized void subOnlineCount() { WebsocketTest.onlineCount--; } }
后台输出:
有新链接加入!当前在线人数为1 来自客户端的消息:123 来自客户端的消息:456
SSE与WebSocket有类似功能,都是用来创建浏览器与服务器之间的通讯渠道。二者的区别在于: