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();
    }
}

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

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值