zoukankan      html  css  js  c++  java
  • Websocket --(2)实现

    首先声明,本篇博文参考文章

    https://blog.csdn.net/jack_eusong/article/details/79064081

    主要在于理解和自己动手搭建环境,自己搭建的过程中会发生很多意想不到的错误。

    1.环境

    Eclipse Mars + jdk1.7 + tomcat8

    2.使用的jar包,spring 的核心jar包就不写了,只写和websocket相关的。

    <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-websocket</artifactId>
             <version>4.0.2.RELEASE</version>
    </dependency>
    
    <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-messaging</artifactId>
             <version>4.0.2.RELEASE</version>
    </dependency>
            
    <dependency>
         <groupId>javax.websocket</groupId>
         <artifactId>javax.websocket-api</artifactId>
         <version>1.1</version>
    </dependency>

    其实我感觉只用 javax.websocket-api 这一个包就够了,可能是我本地环境有问题,如果取消前面两个包Tomcat 无法启动,所以就只能留着了

    搭建完的项目结构如下图

    主要的代码注意一个类,通过@ServerEndpoint注解将类声明为服务端

    package com.lzl.ws;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    
    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;
    
    import org.apache.log4j.Logger;
    import org.springframework.web.socket.server.standard.SpringConfigurator;
    
    @ServerEndpoint(value="/chat/{userId}",configurator = SpringConfigurator.class)
    public class websocketchat{
        public static Logger logger = Logger.getLogger(websocketchat.class);
        
        //在线人数
        public static int onlineCount = 0;
        
         //记录每个用户下多个终端的连接
        private static Map<String, Set<websocketchat>> userSocket = new HashMap<>();
     
        //需要session来对用户发送数据, 获取连接特征userId
        private Session session;
        private String userId;
        
        
        @OnOpen
        public void onOpen(@PathParam("userId") String userId,Session session) throws IOException{
            this.session = session;
            this.userId = userId;
            onlineCount++;
            //根据该用户当前是否已经在别的终端登录进行添加操作
            if (userSocket.containsKey(this.userId)) {
                logger.info("当前用户id:{"+this.userId+"}已有其他终端登录");
                userSocket.get(this.userId).add(this); //增加该用户set中的连接实例
            }else {
                logger.info("当前用户id:{"+this.userId+"}第一个终端登录");
                Set<websocketchat> addUserSet = new HashSet<>();
                addUserSet.add(this);
                userSocket.put(this.userId, addUserSet);
            }
            logger.info("用户{"+userId+"}登录的终端个数是为{"+userSocket.get(this.userId).size()+"}");
            logger.info("当前在线用户数为:{"+userSocket.size()+"},所有终端个数为:{"+onlineCount+"}");
        }
    
        @OnClose
        public void onClose(){
            //移除当前用户终端登录的websocket信息,如果该用户的所有终端都下线了,则删除该用户的记录
            if (userSocket.get(this.userId).size() == 0) {
                userSocket.remove(this.userId);
            }else{
                userSocket.get(this.userId).remove(this);
            }
            logger.info("用户{"+this.userId+"}登录的终端个数是为{"+userSocket.get(this.userId).size()+"}");
            logger.info("当前在线用户数为:{"+userSocket.size()+"},所有终端个数为:{"+onlineCount+"}");
        }
       
        /**
         * @Title: onMessage
         * @Description: 收到消息后的操作
         * @param @param message 收到的消息
         * @param @param session 该连接的session属性
         */
        @OnMessage
        public void onMessage(String message, Session session) {    
            logger.info("收到来自用户id为:{"+this.userId+"}的消息:{"+message+"}");
            if(session ==null)  logger.info("session null");
            //测试向客户端发送消息发送
            logger.info("开始将消息以广播形式发送至所有终端.......");
            sendMessageToUser( this.userId+"说:"+message);
            logger.info("广播结束.......");
        }
       
        /**
         * @Title: onError
         * @Description: 连接发生错误时候的操作
         * @param @param session 该连接的session
         * @param @param error 发生的错误
         */
        @OnError
        public void onError(Session session, Throwable error){
            logger.info("用户id为:{"+this.userId+"}的连接发送错误");
            error.printStackTrace();
        }
       
      /**
       * @Title: sendMessageToUser
       * @Description: 发送消息给用户下的所有终端
       * @param @param userId 用户id
       * @param @param message 发送的消息
       * @param @return 发送成功返回true,反则返回false
       */
        public Boolean sendMessageToUser(String message){
            for(Entry<String, Set<websocketchat>> entry:userSocket.entrySet()){
                logger.info(" 给用户id为:{"+entry.getKey()+"}的所有终端发送消息:{"+message+"}");
                for(websocketchat ws:entry.getValue()){
                     try {
                         ws.session.getBasicRemote().sendText(message);
                     } catch (IOException e) {
                         e.printStackTrace();
                         logger.info(" 给用户id为:{"+userId+"}发送消息失败");
                         return false;
                     }
                }
            }
            return true;
            
        }
    
    }

    前端界面

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
    <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script type="text/javascript">
                $(function() {
                    var websocket;
                    if('WebSocket' in window) {
                                            console.log("此浏览器支持websocket");
                        websocket = new WebSocket("ws://127.0.0.1:8080/websocket/chat/tom");
                    } else if('MozWebSocket' in window) {
                        alert("此浏览器只支持MozWebSocket");
                    } else {
                        alert("此浏览器只支持SockJS");
                    }
                    websocket.onopen = function(evnt) {
                        $("#tou").html("链接服务器成功!")
                    };
                    websocket.onmessage = function(evnt) {
                        $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
                    };
                    websocket.onerror = function(evnt) {};
                    websocket.onclose = function(evnt) {
                        $("#tou").html("与服务器断开了链接!")
                    }
                    
                    
                    
                    
                    $('#send').click(function(){
                        send();
                    });
     
                    function send() {
                        if(websocket != null) {
                            var message = document.getElementById('message').value;
                            websocket.send(message);
                        } else {
                            alert('未与服务器链接.');
                        }
                    }
                });
            </script>
    
    <title>chat</title>
    </head>
    <body>
    <div  >
        <div class="page-header" id="tou" style = "text-align:center">
                webSocket多终端聊天测试
            </div>
            <div class="well" id="msg" style = "800px;margin:0 auto"></div>
            &nbsp;
            <div class="col-lg">
                <div class="input-group" style = "800px;margin:0 auto">
                    <input type="text" class="form-control" placeholder="发送信息..." id="message">
                    <span class="input-group-btn">
                        <button class="btn btn-default" type="button" id="send" >发送</button>
                    </span>
                </div>
            </div>
     </div>
    </body>
    </html>

    在参考文章的基础上将发送消息改为群发形式,即一个人发送所有在线终端均可接收。chat.jsp,chat2.jsp,chat3.jsp用来模拟三个用户的登录。

     websocket = new WebSocket("ws://127.0.0.1:8080/websocket/chat/tom") 中websocket是我的工程名字,chat是服务端路径,tom是服务端参数,定义为用户ID。其实只用写一个界面即可,通过其他方式动态获取用户ID。这里为了方便测试,后续会增加一个登陆功能,然后将用户ID放到session中,获取用户ID后创建websocket对象,类似一个简易的聊天室功能。chat2和chat3 和chat 一模一样,只是更改了路径中的用户ID。这三个用户ID分别是tom jone jack,实现效果如下图。

  • 相关阅读:
    HOW TO MAKE IT FLOW ?
    ansys14.0 从入门到精通
    ansys 14.0
    C++ GUI Qt4 编程 (第二版)
    零基础学QT编程
    医学成像与医学图像处理
    曾巩传
    c++ 编程调试秘笈
    matlab实用教程
    不要重复发明轮子-C++STL
  • 原文地址:https://www.cnblogs.com/li-zhi-long/p/9361517.html
Copyright © 2011-2022 走看看