基于WebSocket实现的用户与用户聊天

一、WebSocket的概述

    WebSocket协议支持(在受控环境中运行不受信任的代码的)客户端与(选择加入该代码的通信的)远程主机之间进行全双工通信。用于此的安全模型是Web浏览器常用的基于原始的安全模式。 协议包括一个开放的握手以及随后的TCP层上的消息帧。 该技术的目标是为基于浏览器的、需要和服务器进行双向通信的(服务器不能依赖于打开多个HTTP连接(例如,使用XMLHttpRequest或<iframe>和长轮询))应用程序提供一种通信机制。

(摘抄自百度百科)

二、websocket的使用

    在这一次的远航政务项目中,有一个需要员工之间进行聊天的功能,由于第一次接触浪费了很多做项目的时间,所以在这里记录下来,避免以后遇到这样的问题又要重新搜百度。

    首先贴前端代码

var websocket = null;
var loginid=sessionStorage.getItem('employeeId');
var loginname=sessionStorage.getItem('employeeName');
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
      websocket = new WebSocket("ws://localhost:8080/websocket/"+loginid+"/"+loginname);
} else {
      alert('Not support websocket')
}

//连接发生错误的回调方法
websocket.onerror = function() {
      setMessageInnerHTML("error");
};

//连接成功建立的回调方法
websocket.onopen = function(event) {
      setMessageInnerHTML("open");
}

//接收到消息的回调方法
websocket.onmessage = function(event) {
      setMessageInnerHTML(event.data);
      console.log(event.data);
}

//连接关闭的回调方法
websocket.onclose = function() {
      setMessageInnerHTML("close");
}

//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
      websocket.close();
}
function setMessageInnerHTML(innerHTML) {
      var uid = document.getElementById('hh').value;
      document.getElementById('message'+uid).innerHTML += innerHTML + '<br/>';
}
//关闭连接
function closeWebSocket() {
      websocket.close();
}
//发送消息
function send() {
      var message = document.getElementById('textarea').value;
      var uid = document.getElementById('hh').value;
      if(uid==null || uid==""){
          alert("请选择一个人聊天把");
          return;
      }
      var sss = message+"|"+uid;
      websocket.send(sss);  //发送信息
      document.getElementById('textarea').value="";       
}

 

贴后端代码:


import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

@ServerEndpoint(value = "/websocket/{loginid}/{loginname}")
@Component
public class Myweb {
    // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。

    private static ConcurrentHashMap<String, Myweb> webSocketSetas = new ConcurrentHashMap<String, Myweb>();
    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    private String userinfo;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("loginid")String loginid,@PathParam("loginname")String loginname, Session session) {
        this.session = session;
        
        userinfo = loginid;
        System.out.println(userinfo);
        System.out.println(loginname);
        webSocketSetas.put(loginid, this);
        addOnlineCount(); // 在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        try {
            // sendMessage(CommonConstant.CURRENT_WANGING_NUMBER.toString());
            sendMessage("建立成功");
        } catch (IOException e) {
            System.out.println("IO异常");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSetas.remove(userinfo); // 从set中删除
        subOnlineCount(); // 在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
    
    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @SuppressWarnings("unused")
    @OnMessage
    public void onMessage(@PathParam("loginname")String loginname,String message) {
        System.out.println("来自客户端的消息:" + message);
        String[] ss = message.split("|");
        String id = ss[ss.length-1];
        System.out.println(id);
        System.out.println(ss[0]+"=============");
        String sss = "";
        for (int i = 2; i <= ss.length; i++) {
            sss += ss[i - 1];
        }
        if ("|".equals(id) || id==null) {
            sendAll(loginname,message);
        } else {
            sendToUser(loginname,message);
        }
        
    }

    // 给指定的人发送消息
    
    public void sendToUser(String loginname,String message) {
        String[] ss = message.split("|");
        String sendUserno = ss[ss.length - 1];
        String sendMessage = "";
        System.out.println(message);
        for (int i = 2; i < ss.length; i++) {
            sendMessage += ss[i - 2];
        }
        String sendUsernomessage="<div class=\"atalk\"><img style='width:30px;height:30px;' src='images/user_img/0.jpg'/>  <span id=\"asay\">"+sendMessage+"</span> </div>";
        String userinfomessage="<div class=\"btalk\"> <span id=\"bsay\">"+sendMessage+"</span> <img style='width:30px;height:30px;' src='images/user_img/0.jpg'/></div>";
        try {
            if (webSocketSetas.get(sendUserno) != null) {
                
                webSocketSetas.get(userinfo).sendMessage(userinfomessage);
                webSocketSetas.get(sendUserno).sendMessage(sendUsernomessage);
            } else {
                System.out.println("当前用户不在线");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendAll(String loginname,String message) {         
        String[] ss = message.split("|");
        String sendMessage = "";
        for (int i = 1; i < ss.length; i++) {
            sendMessage += ss[i - 1];
        }       
        String sendUsernomessage="<div class=\"atalk\"><img style='width:30px;height:30px;' src='images/user_img/0.jpg'/> <span id=\"asay\">  "+sendMessage+"</span> </div>";
        String userinfomessage="<div class=\"btalk\"> <span id=\"bsay\">"+sendMessage+"</span> <img style='width:30px;height:30px;' src='images/user_img/0.jpg'/></div>";
        //遍历HashMap         
        for (String key : webSocketSetas.keySet()) {             
            try {                 
                //判断接收用户是否是当前发消息的用户                
                if (userinfo.equals(key)) {              
                    webSocketSetas.get(userinfo).sendMessage(userinfomessage);
                    System.out.println("key = " + key);                 
                }else {
                    webSocketSetas.get(key).sendMessage(sendUsernomessage);
                }
            } catch (IOException e) {                 
                    e.printStackTrace();             
            }         
        }     
    
        
    }

    /**
     * 发生错误时调用
     *
     * @OnError public void onError(Session session, Throwable error) {
     *          System.out.println("发生错误"); error.printStackTrace(); }
     */

    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() {
        Myweb.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        Myweb.onlineCount--;
    }

posted @ 2018-12-08 15:16  博客小屋  阅读(523)  评论(1编辑  收藏  举报