欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WebSocket,实现简单的广播功能

程序员文章站 2022-05-21 21:26:02
...

改变现在,从通讯开始

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

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

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

相关标签: websocket 前端