websoket服务端主动推动消息客户端
WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。依靠这种技术可以实现客户端和服务器端的长连接,双向实时通信。
特点:
事件驱动
异步
使用ws或者wss协议的客户端socket
能够实现真正意义上的推送功能
缺点:
少部分浏览器不支持,浏览器支持的程度与方式有区别。
三、WebSocket客户端
websocket允许通过JavaScript建立与远程服务器的连接,从而实现客户端与服务器间双向的通信。在websocket中有两个方法:
1、send() 向远程服务器发送数据
2、close() 关闭该websocket链接
websocket同时还定义了几个监听函数
1、onopen 当网络连接建立时触发该事件
2、onerror 当网络发生错误时触发该事件
3、onclose 当websocket被关闭时触发该事件
4、onmessage 当websocket接收到服务器发来的消息的时触发的事件,也是通信中最重要的一个监听事件。msg.data
websocket还定义了一个readyState属性,这个属性可以返回websocket所处的状态:
1、CONNECTING(0) websocket正尝试与服务器建立连接
2、OPEN(1) websocket与服务器已经建立连接
3、CLOSING(2) websocket正在关闭与服务器的连接
4、CLOSED(3) websocket已经关闭了与服务器的连接
websocket的url开头是ws,如果需要ssl加密可以使用wss,当我们调用websocket的构造方法构建一个websocket对象(new WebSocket(url))的之后,就可以进行即时通信了。
<script type="text/JavaScript"> function init() { var websocket = null; var loginuserid=$("#userid").val(); console.log(loginuserid); var strs= new Array(); //定义一数组 //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket = new WebSocket("ws://110.56.17.4/websocket?"+loginuserid); } else{ alert('Not support websocket'); } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(event){ setMessageInnerHTML("open"); }; //接收到消息的回调方法 websocket.onmessage = function(event){ setMessageInnerHTML(event.data); }; //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); }; //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); }; //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ //document.getElementById('message').innerHTML += innerHTML + '<br/>'; if(innerHTML=="一级告警") { $("#soundid1").empty(); var div = document.getElementById('soundid1'); div.innerHTML = '<audio src="'+"<%= path %>/jsp/sound/ALARM1.WAV"+'" hidden="true" autoplay="true" loop="false"></audio>'; } else if(innerHTML=="二级告警") { $("#soundid1").empty(); var div = document.getElementById('soundid1'); if(div!=null) { div.innerHTML = '<audio src="'+"<%= path %>/jsp/sound/ALARM3.WAV"+'" hidden="true" autoplay="true" loop="false"></audio>'; } } } //关闭连接 function closeWebSocket(){ websocket.close(); } //发送消息 function send(){ var message = document.getElementById('text').value; websocket.send(message); } } </script>
WebSocket服务器端
package com.maven.websocket; import java.io.IOException; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint(value = "/websocket") public class MyWebSocket{ //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 * @throws Exception */ @OnOpen public void onOpen(Session session) throws Exception{ this.session = session; WebSocketMapUtil.put(session.getQueryString(),this); addOnlineCount(); //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); } /** * 连接关闭调用的方法 * @throws Exception */ @OnClose public void onClose() throws Exception{ //从map中删除 WebSocketMapUtil.remove(session.getQueryString()); subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * @param session 可选的参数 * @throws IOException */ @OnMessage public void onMessage(String message, Session session) throws IOException { String sendUserID = message.split("[|]")[1]; String sendMessage = message.split("[|]")[0]; try { if (WebSocketMapUtil.get(sendUserID) != null) { WebSocketMapUtil.get(sendUserID).sendMessage(sendMessage); } else { System.out.println("当前用户不在线!"+WebSocketMapUtil.get(sendUserID)+sendUserID); } } catch (IOException e) { e.printStackTrace(); } /*try { MyWebSocket myWebSocket= ((MyWebSocket) WebSocketMapUtil.get(session.getQueryString().replace("service","client"))); if(myWebSocket != null){ myWebSocket.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); }*/ } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ error.printStackTrace(); } /** * 发送消息方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); } /** * 群发消息方法。 * @param message * @throws IOException */ public void sendMessageAll(String message) throws IOException{ for(MyWebSocket myWebSocket : WebSocketMapUtil.getValues()){ myWebSocket.sendMessage(message); } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { MyWebSocket.onlineCount++; } public static synchronized void subOnlineCount() { MyWebSocket.onlineCount--; } }
package com.maven.websocket; import java.io.IOException; import java.net.URI; import javax.websocket.ClientEndpoint; import javax.websocket.ContainerProvider; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.WebSocketContainer; @ClientEndpoint public class MyClient { private Session session; @OnOpen public void onOpen(Session session) throws IOException { this.session = session; } @OnMessage public void onMessage(String message) { } @OnError public void onError(Throwable t) { t.printStackTrace(); } /** * 连接关闭调用的方法 * @throws Exception */ @OnClose public void onClose() throws Exception{ } /** * 关闭链接方法 * @param message * @throws IOException */ public void closeSocket() throws IOException{ this.session.close(); } /** * 发送消息方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); } //启动客户端并建立链接 public void start(String uri) { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); try { this.session = container.connectToServer(MyClient.class, URI.create(uri)); } catch (Exception e) { e.printStackTrace(); } } }
package com.maven.websocket; import java.io.IOException; public class MyClientApp { public static void main(String[] args){ MyClient client = new MyClient(); client.start(new WebSocketMapUtil().url); try { client.sendMessage("一级告警|12132313"); client.closeSocket(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.maven.websocket; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class WebSocketMapUtil { public String url = "ws://110.56.17.4/websocket?service123"; public static ConcurrentMap<String, MyWebSocket> webSocketMap = new ConcurrentHashMap<String, MyWebSocket>(); public static void put(String key, MyWebSocket myWebSocket){ webSocketMap.put(key, myWebSocket); } public static MyWebSocket get(String key){ return webSocketMap.get(key); } public static void remove(String key){ webSocketMap.remove(key); } public static Collection<MyWebSocket> getValues(){ return webSocketMap.values(); } }