美文网首页Java-Tools
WebSocket 心跳 登陆 实例代码!

WebSocket 心跳 登陆 实例代码!

作者: Ay鑫 | 来源:发表于2019-04-24 15:08 被阅读0次

    · JS-前端代码.

    var websocket;//websocket实例
    var lockReconnect = false;//避免重复连接
    var userno="123";
    
    var wsUrl = "ws://localhost:8080/test/websocket/"+userno;
    
    function createWebSocket(url) {
        try {
            websocket = new WebSocket(url);
            initEventHandle();
        } catch (e) {
            reconnect(url);
        }     
    }
    
    function initEventHandle() {
        websocket.onclose = function () {
            console.log("WebSocket连接已经关闭");
            reconnect(wsUrl);
        };
        websocket.onerror = function () {
            console.log("WebSocket连接发生错误");
            reconnect(wsUrl);
        };
        websocket.onopen = function () {
            console.log("WebSocket连接已经成功");
            //心跳检测重置
            heartCheck.reset().start();
        };
        websocket.onmessage = function (event) {
            setMessageInnerHTML(event.data);
            //如果获取到消息,心跳检测重置
            //拿到任何消息都说明当前连接是正常的
            heartCheck.reset().start();
        }
    }
    
    //重新连接webSocket
    function reconnect(url) {
        if(lockReconnect) return;
        lockReconnect = true;
        //没连接上会一直重连,设置延迟避免请求过多
        setTimeout(function () {
            createWebSocket(url);
            lockReconnect = false;
        }, 2000);
    }
    
    //心跳检测
    var heartCheck = {
        timeout: 60000,//60秒
        timeoutObj: null,
        serverTimeoutObj: null,
        reset: function(){
            clearTimeout(this.timeoutObj);
            clearTimeout(this.serverTimeoutObj);
            return this;
        },
        start: function(){
            var self = this;
            this.timeoutObj = setTimeout(function(){
                //这里发送一个心跳,后端收到后,返回一个心跳消息,
                //onmessage拿到返回的心跳就说明连接正常
                websocket.send("HeartBeat");
                self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
                    websocket.close();//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
                }, self.timeout)
            }, this.timeout)
        }
    }
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        //初始化连接webSocket
        createWebSocket(wsUrl);
    }
    else {
        alert('当前浏览器 Not support websocket')
    }
    
    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        console.log(innerHTML);
        var data = JSON.parse(innerHTML);
        console.log("-------------- websocket -----------------------------------");
        
    }
    
    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }
    
    //发送消息
    function send(message) {
        websocket.send(message);
    }
    
    

    · JAVA-后端代码.

    package com.ay.websocket;
    
    
    import javax.websocket.*;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    import java.io.IOException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.ConcurrentHashMap;
    
    
    @ServerEndpoint("/websocket/{userno}")
    public class WebSocket {
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
        private static ConcurrentHashMap<String, WebSocket> webSocketSet = new ConcurrentHashMap<String, WebSocket>();
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
        //当前发消息的人员编号
        private String userno = "";
    
        /**
         * 连接建立成功调用的方法
         *
         * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
        @OnOpen
        public void onOpen(@PathParam(value = "userno") String param, Session session, EndpointConfig config) {
            System.out.println(param);
            userno = param;//接收到发送消息的人员编号
            this.session = session;
            webSocketSet.put(param, this);//加入map中
            addOnlineCount();           //在线数加1
            System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            if (!userno.equals("")) {
                webSocketSet.remove(userno);  //从set中删除
                subOnlineCount();           //在线数减1
                System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
            }
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         * @param session 可选的参数
         */
        @SuppressWarnings("unused")
    //  @OnMessage
        public void onMessage(String message, Session session) {
            System.out.println("来自客户端的消息:" + message);
    //        session.get
            //群发消息
            if (1 < 2) {
                sendAll(message);
            } else {
                //给指定的人发消息
                sendToUser(message);
            }
        }
    
        /**
         * 给指定的人发送消息
         * @param message
         */
        @OnMessage
        public void sendToUser(String message) {
            String sendUserno = message.split("[|]")[1];
            String sendMessage = message.split("[|]")[0];
            String now = getNowTime();
            try {
                if (webSocketSet.get(sendUserno) != null) {
                    webSocketSet.get(sendUserno).sendMessage(now + "用户" + userno + "发来消息:" + " <br/> " + sendMessage);
                } else {
                    System.out.println("当前用户不在线");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 给所有人发消息
         * @param message
         */
        private void sendAll(String message) {
            String now = getNowTime();
            String sendMessage = message.split("[|]")[0];
            //遍历HashMap
            for (String key : webSocketSet.keySet()) {
                try {
                    //判断接收用户是否是当前发消息的用户
                    if (!userno.equals(key)) {
                        webSocketSet.get(key).sendMessage(now + "用户" + userno + "发来消息:" + " <br/> " + sendMessage);
                        System.out.println("key = " + key);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        /**
         * 获取当前时间
         *
         * @return
         */
        private String getNowTime() {
            Date date = new Date();
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = format.format(date);
            return time;
        }
        /**
         * 发生错误时调用
         *
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            System.out.println("发生错误");
            error.printStackTrace();
        }
    
        /**
         * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
         *
         * @param message
         * @throws IOException
         */
        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() {
            WebSocket.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocket.onlineCount--;
        }
    
    
    
    
        public static void send2User(String sendUserno,String sendMessage){
            try {
                if (webSocketSet.get(sendUserno) != null) {
                    webSocketSet.get(sendUserno).sendMessage(sendMessage);
                } else {
                    System.out.println("当前用户不在线");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * 给所有人发消息
         * @param message
         */
        public static void sendAlls(String message) {
    
            String sendMessage = message.split("[|]")[0];
            //遍历HashMap
            for (String key : webSocketSet.keySet()) {
                try {
                    //判断接收用户是否是当前发消息的用户
                    webSocketSet.get(key).sendMessage(sendMessage);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
    }
    
    

    相关文章

      网友评论

        本文标题:WebSocket 心跳 登陆 实例代码!

        本文链接:https://www.haomeiwen.com/subject/kasggqtx.html