websocket 心跳链接

websocket链接时,若是长时间没有进行数据的通信就会自动断开链接。为了避免让其断开就在要断开的时候自动发送数据进行通信,就产生了心跳链接的效果。javascript

具体的操做就是在客户端创建链接的时候开启发送心跳信息的线程,以后再每次收到信息以后就线程重启。服务端在处理数据的时候多处理一下心跳信息,将其发给链接的用户,从而实现心跳通信。java

服务端代码web

@ServerEndpoint("/video")
public class AcgistVideo {
    //链接超时
    public static final long MAX_TIME_OUT = 2 * 60 * 1000;
    //房间和房间对应的用户列表
    public static Map<String, ArrayList<String>> room_user = Collections.synchronizedMap(new HashMap<String, ArrayList<String>>());
    //用户的sid和用户的session一一对应
    public static Map<String, Session> user_session = Collections.synchronizedMap(new HashMap<String, Session>());
    //用户的sid和房间一一对应
    public static Map<String, String> userInRoom = Collections.synchronizedMap(new HashMap<String, String>());
    public static Logger log = LoggerFactory.getLogger(AcgistVideo.class);

    /**
     * 打开websocket
     *
     * @param session websocket的session
     * @param uid     打开用户的UID
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) throws IOException {
        log.info("--------------------onOpen--------------------");
        session.setMaxIdleTimeout(MAX_TIME_OUT);
    }
    /**
     * 收到消息
     *
     * @param message 消息内容
     * @param session 发送消息的session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("接收到来自客户端--" + session.getId() + "--的信息:" + message);
        JSONObject json = JSONObject.fromObject(message);

        if (json.get("type").equals("create")) {
            ArrayList arrayList = new ArrayList();
            arrayList.add(session.getId());

            String roomId = createRoom();
            room_user.put(roomId, arrayList);
            userInRoom.put(session.getId(), roomId);
            user_session.put(session.getId(), session);

            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "create");
            jsonstr.put("room", roomId);
            jsonstr.put("sid", session.getId());
            jsonstr.put("count", getUserNumberByRoom(roomId));
            sendMessage(jsonstr.toString(), session);

        } else if (json.get("type").equals("apply")) {
            String roomId = "";
            if (json.has("room")) {
                roomId = json.getString("room");
            }

            if (!("".equals(roomId)) && null != room_user.get(roomId)) {
                ArrayList<String> arrayList = room_user.get(roomId);
                arrayList.add(session.getId());
                room_user.put(roomId, arrayList);
                userInRoom.put(session.getId(), roomId);
                user_session.put(session.getId(), session);

                JSONObject jsonstr = new JSONObject();
                jsonstr.put("type", "apply");
                jsonstr.put("room", roomId);
                jsonstr.put("sid", session.getId());
                jsonstr.put("count", getUserNumberByRoom(roomId));

                sendMessageToUserInSameRoom(session.getId(), jsonstr, false);
            } else {
                ArrayList arrayList = new ArrayList();
                arrayList.add(session.getId());

                roomId = createRoom();
                room_user.put(roomId, arrayList);
                userInRoom.put(session.getId(), roomId);
                user_session.put(session.getId(), session);

                JSONObject jsonstr = new JSONObject();
                jsonstr.put("type", "create");
                jsonstr.put("room", roomId);
                jsonstr.put("sid", session.getId());
                jsonstr.put("count", getUserNumberByRoom(roomId));
                sendMessage(jsonstr.toString(), session);
            }
        } else if (json.get("type").equals("receipt")) {
            Session oession = user_session.get(json.get("sid"));
            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "receipt");
            jsonstr.put("room", json.get("room"));
            jsonstr.put("sid", session.getId());
            jsonstr.put("count", getUserNumberByRoom(userInRoom.get(session.getId())));
            sendMessage(jsonstr.toString(), oession);
        } else if (json.get("type").equals("link")) {
            Session oession = user_session.get(json.get("sid"));
            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "link");
            jsonstr.put("room", json.get("room"));
            jsonstr.put("sid", session.getId());
            jsonstr.put("count", getUserNumberByRoom(userInRoom.get(session.getId())));
            sendMessage(jsonstr.toString(), oession);
        } else if (json.get("type").equals("offer")) {
            Session oession = user_session.get(json.get("sid"));
            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "offer");
            jsonstr.put("room", json.get("room"));
            jsonstr.put("sid", session.getId());
            jsonstr.put("count", getUserNumberByRoom(userInRoom.get(session.getId())));
            jsonstr.put("offer", json.get("offer"));
            sendMessage(jsonstr.toString(), oession);
        } else if (json.get("type").equals("answer")) {
            Session oession = user_session.get(json.get("sid"));
            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "answer");
            jsonstr.put("room", json.get("room"));
            jsonstr.put("sid", session.getId());
            jsonstr.put("count", getUserNumberByRoom(userInRoom.get(session.getId())));
            jsonstr.put("answer", json.get("answer"));
            sendMessage(jsonstr.toString(), oession);
        } else if (json.get("type").equals("candidate")) {
            Session oession = user_session.get(json.get("sid"));
            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "candidate");
            jsonstr.put("room", json.get("room"));
            jsonstr.put("sid", session.getId());
            jsonstr.put("count", getUserNumberByRoom(userInRoom.get(session.getId())));
            jsonstr.put("candidate", json.get("candidate"));
            sendMessage(jsonstr.toString(), oession);
        } else if (json.get("type").equals("bye")) {
            remove(session);
        } else if (json.get("type").equals("beat")) {
            JSONObject jsonstr = new JSONObject();
            jsonstr.put("type", "beat");
            jsonstr.put("msg", json.get("msg"));
            jsonstr.put("sid", session.getId());
            sendMessageToUserInSameRoom(session.getId(), jsonstr, false);
        }
    }
    /**
     * websocket错误
     *
     * @param e
     * @param session
     */
    @OnError
    public void onError(Throwable e, Session session) {
        log.info("--------------------onError--------------------");
        log.info("session ID: --" + session.getId() + " --离开了");
        log.error("--", e);
        log.info("----------------------------------------");
    }
    /**
     * websocket关闭
     *
     * @param session 关闭的session
     */
    @OnClose
    public void onClose(Session session) {
        log.info("--------------------onClose--------------------");
        remove(session);
    }
    /**
     *    * 随机生成UUID
     *    * @return
     *    
     */
    public static synchronized String getUUID() {
        log.info("--------------------getUUID--------------------");
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString();
        String uuidStr = str.replace("-", "");
        return uuidStr;
    }
    /**
     * 经过房间号获取房间中的用户数量
     *
     * @param roomId 房间号
     * @return 房间中的用户数量 若是只为-1则房间不存在
     */
    public int getUserNumberByRoom(String roomId) {
        log.info("--------------------getUserNumberByRoom--------------------");
        if (room_user.containsKey("roomId")) {
            ArrayList<String> userList = room_user.get(roomId);
            return userList.size();
        } else {
            return -1;
        }
    }
    /**
     * 发送信息
     *
     * @param message 发送内容
     * @param session 用户session
     */
    public void sendMessage(String message, Session session) {
        log.info("--------------------sendMessage--------------------");
        try {
            log.info("发送消息到客户端--" + session.getId() + "--信息为:" + message);
            synchronized (session) {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                }
            }
        } catch (Exception e) {
            log.error("send message exception", e);
        }
    }
    /**
     * 建立房间
     *
     * @return 房间ID
     */
    public String createRoom() {
        log.info("--------------------createRoom--------------------");
        String roomId = getUUID();
        return roomId;
    }
    /**
     * 移除聊天用户
     *
     * @param session 移除的session
     */
    private void remove(Session session) {
        log.info("--------------------remove--------------------");

        String roomId = userInRoom.get(session.getId());
        ArrayList<String> arrayList = room_user.get(roomId);

        if (arrayList.contains(session.getId())) {
            log.info("移除SID:" + session.getId());
            arrayList.remove(session.getId());
            if (arrayList.size() < 1) {
                log.info("移除房间:" + roomId);
                room_user.remove(roomId);
            } else {
                room_user.put(roomId, arrayList);

                //用户退出的时候给房间中的每一位用户发一条信息
                JSONObject jsonstr = new JSONObject();
                jsonstr.put("type", "bye");
                jsonstr.put("sid", session.getId());
                sendMessageToUserInSameRoom(session.getId(), jsonstr, false);
            }
            userInRoom.remove(session.getId());
            user_session.remove(session.getId());
        }
    }
    /**
     * 给用户所在房间中的每一位用户发一条信息
     *
     * @param selfId     用户Id
     * @param jsonstr    须要发的信息
     * @param isSendSelf 是否发给本身
     */
    private void sendMessageToUserInSameRoom(String selfId, JSONObject jsonstr, boolean isSendSelf) {
        String roomId = userInRoom.get(selfId);
        ArrayList<String> arrayList = room_user.get(roomId);

        for (int i = 0; i < arrayList.size(); i++) {
            if (arrayList.get(i).equals(selfId)) {
                if (isSendSelf) {
                    sendMessage(jsonstr.toString(), user_session.get(arrayList.get(i)));
                }
            } else {
                sendMessage(jsonstr.toString(), user_session.get(arrayList.get(i)));
            }
        }
    }
}
客户端代码

var MyWebSocket = function (obj) {
    var _this = this;
    this.timeout = 30 * 1000;
    this.timeoutObj = null;
    this.socket = null;
    this.initSocket = function () {
        this.socket = new WebSocket(GLOBAL.getConstant("WEB_SOCKET_URL"));

        this.socket.onopen = function () {
            console.log("websocket-----> Opened");
            _this.start();
        };

        this.socket.onmessage = this.socketMessage;

        this.socket.onclose = function () {
            console.log("websocket-----> Closed");
            obj.closeWebSocket();
        };

        this.socket.onerror = function () {
            console.log("websocket-----> Error:" + JSON.stringify(event));
        };

        console.log("-------websocket初始化完成执行回调函数-------");
        obj.initWebRtc(obj.entitys);
    }
    //接收到服务器的回复
    this.socketMessage = function (message) {
        console.log("websocket-----> Message:" + message.data);
        _this.reset();
        obj.SocketCallBack(message.data);
    }
    //向服务器发送信息
    this.sendMessage = function (message, callback) {
        this.waitForConnection(function () {
            var msgJson = JSON.stringify(message);
            this.socket.send(msgJson);
            console.log("websocket-----> SendMessage:" + msgJson);
            if (typeof callback !== 'undefined') {
                callback();
            }
        }, 1000);
    };
    this.waitForConnection = function (callback, interval) {
        if (this.socket.readyState === 1) {
            callback();
        } else {
            var that = this;
            setTimeout(function () {
                that.waitForConnection(callback, interval);
            }, interval);
        }
    };
    this.onClose = function () {
        this.socket.close();
    }
    this.start = function () {
        _this.timeoutObj = setTimeout(function () {
            var heartbeat = {
                type: "beat",
                msg: "HeartBeat"
            };
            _this.socket.send(JSON.stringify(heartbeat));
        }, _this.timeout)
    };
    this.reset = function () {
        clearTimeout(this.timeoutObj);
        _this.start();
    };

    this.initSocket();

    return this;
}