WebSocket,实现简单的广播功能

来源:互联网 发布:软件开发方向 编辑:程序博客网 时间:2024/06/05 09:40

改变现在,从通讯开始

传统的前端和后端的数据交互是使用轮询方法,会占用大量资源。在如今高速发展的时代,一种能提升效率的方法或者说新技术便显得尤为重要。
websocket便是这样一种技术,有关于它的更多的一些细节,大家可以自行百度。(本博客部分代码来源自网上,向前辈们致敬)
这里看一下广播的演示结果:
这里写图片描述

不写代码,终究是纸上谈兵

(csdn不能把资源免费了!)
websocket jar包下载

这里只是展示websocket的一个小demo,并未对界面做过多要求。于是只设计了一个简单的发送消息文本框和按钮。加载页面时初始化socket,点击按钮触发socket.send(msg)方法便可。由于是多客户端广播,每一个socket在连接服务器时需要加上自己相应的id参数。(这里生成id参数方法并不推荐)

<%-- Created by IntelliJ IDEA. --%><%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head>  <meta name="viewport" content="width=device-width" />  <title>WebSocket 客户端</title></head><body><div>  <div class="main">    <input name="message" id="msg" onkeydown="if (event.keyCode==13) sendMsg()"/>    <button onclick="sendMsg()">发送</button>  </div></div><script src="resource/js/jquery.js" type="text/javascript" charset="utf-8"></script><script src="resource/js/socket.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">     var uid = getRandomWithoutRepeat([1,2,3,4,5,6,7,8,9,10]);//获取当前账户的id;     var url="ws://127.0.0.1:8080/webSocketServer/"+uid[0];     var socket = getSocket(url);     bindMethod(socket);     function sendMsg() {       Log("发送:"+$("#msg").val(),"INFO");       socket.send($("#msg").val());       $("#msg").val("")     }     window.onbeforeunload = function() {       socket.close();     };     /**      * 创建随机数      * @param Min      * @param Max      * @returns {*}      * @constructor      */     function getRandom(Min,Max){       var Range = Max - Min;       var Rand = Math.random();       return(Min + Math.round(Rand * Range));     }     /**      * 获取不重复的随机数      * @param arr      * @returns {Array}      */     function getRandomWithoutRepeat(arr){       var temp=[];    //temp存放生成的随机数组       for (var i=0;i<arr.length;i++)       {         var num=Math.floor(Math.random()*arr.length); //生成随机数num         temp.push(arr[num]);    //获取arr[num]并放入temp         arr.splice(num,1);       }       return temp;     }</script></body></html>

可以发现上述界面部分引入了socket.js文件,这个是我自己抽象出来的一部分可供重用的方法部分,比如说打印日志和创建websocket的代码。

/** * Created by zipple on 2017/9/28. * 创建web socket 对象 * 定义相关方法 *//** * 创建socket对象 * @param url * @returns {WebSocket} */function getSocket(url) {    if(typeof(WebSocket) == "undefined") { //此处判断支持Android        alert("您的浏览器不支持WebSocket");    }    Log("建立socket对象","OK");    return new WebSocket(url);}/** * 为创建的socket对象绑定相关方法 * @param ws * @param elements 获取信息的地方 */function bindMethod(ws) {    ws.onopen = function () {      Log("连接成功","OK")    };    ws.onmessage = WSonMessage;    ws.onclose = WSonClose;    ws.onerror = WSonError;}/** * 获取数据 * @param event */function WSonMessage(event) {    Log("获取到信息:"+event.data,"OK");    var div = "<div>"+event.data+"</div>";    $("body").prepend($(div))}/** * 关闭连接 */function WSonClose() {    Log("连接关闭。", "ERROR");}/** * 链接异常 */function WSonError() {    Log("WebSocket错误。", "ERROR");}/** * 在控制台打印数据 * @param msg * @param type */function Log(msg,type) {    switch (type){        case 0 :            type="ERROR";            break;        case 1:            type="OK";            break;        case 2:            type="WARNING";            break;        default:            type="INFO"    }    console.log(type+":"+msg+" at "+getNowFormatDate());}/** * 获取系统当前时间 * @returns {string} */function getNowFormatDate() {    var currentdate="error occurred in getNoeFormatDate";    var date = new Date();    var seperator1 = "-";    var seperator2 = ":";    var month = date.getMonth() + 1;    var strDate = date.getDate();    if (month >= 1 && month <= 9) {        month = "0" + month;    }    if (strDate >= 0 && strDate <= 9) {        strDate = "0" + strDate;    }    currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate        + " " + date.getHours() + seperator2 + date.getMinutes()        + seperator2 + date.getSeconds();    return currentdate;}

后台:接收连接请求,储存session,遍历对象,转发msg

为了实现用户的广播(即将某个用户发送到服务器端的信息转发至所有用户)功能,我们需要在接收到用户websocket连接请求时储存当前用户的session,用于转发数据。
因为这只是一个简单的demo入门,便不再考虑其他的相关安全操作,下线判断等等。

package webSocket;import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.concurrent.CopyOnWriteArraySet;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;/** * 多个用户之间的通讯 */@ServerEndpoint("/webSocketServer/{userId}")public class WebSocketServer {    private Session session;    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();    /**     * 连接建立成功调用的方法     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据     */    @OnOpen    public void onOpen(@PathParam("userId") String userId,Session session){        System.out.println("Client connected  "+userId);//在这里储存用户        this.session =session;        webSocketSet.add(this);    }    /**     * 连接关闭调用的方法     */    @OnClose    public void onClose(@PathParam("userId") String userId){        System.out.println("Connection closed");    }    /**     * 收到客户端消息后调用的方法     * @param message 客户端发送过来的消息     */    @OnMessage    public void onMessage(@PathParam("userId") String userId,String message) throws IOException {        System.out.println("服务器接收用户"+userId+"消息: " + message);        for (WebSocketServer ws: webSocketSet){            ws.session.getBasicRemote().sendText("服务器回复:"+message);        }    }    /**     * 发生错误时调用     * @param session     * @param error     */    @OnError    public void onError(Session session, Throwable error){        error.printStackTrace();    }}

好吧!
其实是写这篇博客的时候太困了!
坚持不住了,就直接把所有源码贴上来了。
没有做过多解释,请同行见谅。

你逃避的北上广,是我曾向往过的远方