websocket实现聊天室等功能

9 篇文章 0 订阅
1 篇文章 0 订阅

最近有做一个h5项目,有如下场景需求:
1.实现实时聊天。
2.多人登录,有一个教师角色可控制其他角色用户的视频播放(播放,暂停,快进)。
最初考虑视频控制的实现方向是推流,但是由于没有接触过这方面,着实头疼了一阵。最后,经过一夜梦中思考,次日上午,采用指令的方式实现对视频的控制。
是不是听着很高大上?其实很简单,以上两个功能都是通过onmessage函数实现,将教师端的页面加上监控视频的事件,以指令的方式发送至学生端。

以下是一些核心代码:
后端java代码:

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class WebSocketMessageInboundPool {

    //保存连接的MAP容器
    private static final Map<String,WebSocketMessageInbound > connections = new HashMap<String,WebSocketMessageInbound>();

    //向连接池中添加连接
    public static void addMessageInbound(WebSocketMessageInbound inbound){
        //添加连接
        System.out.println("user : " + inbound.getUser() + " join..");
        connections.put(inbound.getUser(), inbound);
    }

    //获取所有的在线用户
    public static Set<String> getOnlineUser(){
        return connections.keySet();
    }

    public static void removeMessageInbound(WebSocketMessageInbound inbound){
        //移除连接
        System.out.println("user : " + inbound.getUser() + " exit..");
        connections.remove(inbound.getUser());
    }

    public static void sendMessageToUser(String user,String message){
        try {
            //向特定的用户发送数据
            System.out.println("send message to user : " + user + " ,message content : " + message);
            WebSocketMessageInbound inbound = connections.get(user);
            if(inbound != null){
                inbound.getWsOutbound().writeTextMessage(CharBuffer.wrap(message));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //向所有的用户发送消息
    public static void sendMessage(String message){
        try {
            Set<String> keySet = connections.keySet();
            for (String key : keySet) {
                WebSocketMessageInbound inbound = connections.get(key);
                if(inbound != null){
                    System.out.println("send message to user : " + key + " ,message content : " + message);
                    inbound.getWsOutbound().writeTextMessage(CharBuffer.wrap(message));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import net.sf.json.JSONObject;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;

public class WebSocketMessageInbound extends MessageInbound {

    //当前连接的用户名称
    private final String user;

    public WebSocketMessageInbound(String user) {
        this.user = user;
    }

    public String getUser() {
        return this.user;
    }

    //建立连接的触发的事件
    @Override
    protected void onOpen(WsOutbound outbound) {
        // 触发连接事件,在连接池中添加连接
        JSONObject result = new JSONObject();
        result.element("type", "user_join");
        result.element("user", this.user);
        //向所有在线用户推送当前用户上线的消息
//      WebSocketMessageInboundPool.sendMessage(result.toString());

        result = new JSONObject();
        result.element("type", "get_online_user");
        result.element("list", WebSocketMessageInboundPool.getOnlineUser());
        //向连接池添加当前的连接对象
        WebSocketMessageInboundPool.addMessageInbound(this);
        //向当前连接发送当前在线用户的列表
//      WebSocketMessageInboundPool.sendMessageToUser(this.user, result.toString());
    }

    @Override
    protected void onClose(int status) {
        // 触发关闭事件,在连接池中移除连接
        WebSocketMessageInboundPool.removeMessageInbound(this);
        /*JSONObject result = new JSONObject();
        result.element("type", "user_leave");
        result.element("user", this.user);
        //向在线用户发送当前用户退出的消息
        WebSocketMessageInboundPool.sendMessage(result.toString());*/
    }

    @Override
    protected void onBinaryMessage(ByteBuffer message) throws IOException {
        throw new UnsupportedOperationException("Binary message not supported.");
    }

    //客户端发送消息到服务器时触发事件
    @Override
    protected void onTextMessage(CharBuffer message) throws IOException {
        JSONObject jsStr = JSONObject.fromObject(message.toString());
        System.out.println(message.toString());
        if(jsStr.containsKey("to")){
            String uid = jsStr.getString("to");
            WebSocketMessageInboundPool.sendMessageToUser(uid, message.toString());
        }else{
            //向所有在线用户发送消息
            WebSocketMessageInboundPool.sendMessage(message.toString());
        }
    }
}
import java.util.concurrent.atomic.AtomicInteger;  

import javax.servlet.http.HttpServletRequest;  

import org.apache.catalina.websocket.StreamInbound;  
import org.apache.catalina.websocket.WebSocketServlet;  

public class HelloWebSocketServlet extends WebSocketServlet {  
    private static final long serialVersionUID = 1L;  

    private final AtomicInteger connectionIds = new AtomicInteger(0);  
  //跟平常Servlet不同的是,需要实现createWebSocketInbound,在这里初始化自定义的WebSocket连接对象
    @Override
    protected StreamInbound createWebSocketInbound(String subProtocol,HttpServletRequest request) {
        return new WebSocketMessageInbound(this.getUser(request));
    }
    public String getUser(HttpServletRequest request){
        return (String) request.getParameter("id");
    }
}  

前端js:
教师端

var websocket;
var audio = document.getElementById('event_video'); 
//var wsUrl = "ws://daxin.tunnel.qydev.com/yanl-websocket/websocket/say?id=";
var wsUrl = "ws://"+ipaddr+"/yanl-websocket/websocket/say?id=";
//var wsUrl = "ws://127.0.0.1:8080/yanl-websocket/websocket/say?id=";
//视频控制
var video = {
    timer:null,
    audioStat : false,
    reset : function(){
         audio.currentTime = 0;
    },
    play : function(){
        if(audio!==null){
            video.audioStat = true;
            user_ws.allSendInstructions(video_flag.play + Math.ceil(audio.currentTime));
        }
    },
    monitoring : function (){
        //关闭之前开启的定时事件
        if(video.timer != null){
            window.clearInterval(video.timer);
        }
        var time1 = audio.currentTime;
        video.timer = setInterval(function(){
            time2 = time1;
            time1 = audio.currentTime;
            console.info(time1-time2);
            if((time1-time2)>1){
                console.info("快进了");
                user_ws.allSendInstructions(video_flag.go_to + Math.ceil(time1));
            }else if(audio.paused && video.audioStat){
                video.audioStat = false;
                user_ws.allSendInstructions(video_flag.pause + Math.ceil(time1));
            }
            if(time1 == audio.duration || time1 == 0){
                window.clearInterval(video.timer);
                console.info("暂停了");
            }
        },300);
    }
}

var user_ws = {
    crid : "",
    userList : [],
    user_guid : "",
    name : "",
    send : function(toId,content,instructions){
        var data={};
        data.to = toId;
        data.from = user_ws.user_guid;
        data.content = content;
        data.type = instructions == null ? 'message':instructions;
        websocket.send(JSON.stringify(data));
    },
    allSendInstructions : function(content){
        for ( var u in users.list) {
            if(users.list[u].realizeUsers != null && users.list[u].realizeUsers != ""){
                for ( var uu in users.list[u].realizeUsers) {
                    user_ws.send(users.list[u].realizeUsers[uu].su_id,content,'instructions');
                }
            }
        }
    },
    allSend : function(content){
        for ( var u in users.list) {
            if(users.list[u].realizeUsers != null && users.list[u].realizeUsers != ""){
                for ( var uu in users.list[u].realizeUsers) {
                    user_ws.send(u.user_suid,content);
                }
            }
        }
    },
    eventChange : function(){
        user_ws.allSendInstructions("eventChange");
    }
}

$(document).ready(function() {

    var suid = sessionStorage.getItem("suid");
    suid = JSON.parse(suid); 
    //用户的全局唯一标识:个人id
    user_ws.user_guid = suid.data.su_id;
    ws_com.user_guid = suid.data.su_id;
    user_ws.name = suid.data.su_name;
    user_ws.crid = sessionStorage.getItem("crid");
    //初始化websocket
    if ('WebSocket' in window) {
        websocket = new WebSocket(wsUrl + user_ws.user_guid);
    } 
    websocket.onmessage = function(event) {
        var data=JSON.parse(event.data);
        if(data.type == "message"){
            if(!($(this).hasClass('active'))) {
                $("#message").addClass("active");
                $(".message").css("visibility", "visible");
                $(".message").css("z-index",10);
            }
            //接收聊天内容
            var content = JSON.parse(data.content);
            ws_com.createRecord(content);
        }
    };
  });

function yp(){
    var ypv = $("#ylpx").val();
    user_ws.allSendInstructions(ypv);
}

$("#content_c").mousedown(function(e){
        if(e&&e.stopPropagation){//非IE
               e.stopPropagation();
              }
              else{//IE
               window.event.cancelBubble=true;
              }
});
$("#messAll").mousedown(function(e){
    if(e&&e.stopPropagation){//非IE
        e.stopPropagation();
    }
    else{//IE
        window.event.cancelBubble=true;
    }
});
$("#userList_c").mousedown(function(e){
    if(e&&e.stopPropagation){//非IE
        e.stopPropagation();
    }
    else{//IE
        window.event.cancelBubble=true;
    }
});

学生端:

// 初始化websocket
var websocket;
var audio = document.getElementById('v');
var wsUrl = "ws://"+ipaddr+"/yanl-websocket/websocket/say?id=";
//var wsUrl = "ws://127.0.0.1:8080/yanl-websocket/websocket/say?id=";
//var wsUrl = "ws://daxin.tunnel.qydev.com/yanl-websocket/websocket/say?id=";

var video = {
    pause : function (time){
        audio.currentTime = time;
        audio.pause();
    },
    play : function(time){
        if (audio !== null) {
            if (audio.currentTime == 0) {
                audio.play();
            } else {
                audio.currentTime = time;
                audio.play();
            }
        }
    },
    go_to : function(time){
        audio.currentTime = time;
        audio.play();
    }
}

$(function(){
    var suid = sessionStorage.getItem("suid");
    suid = JSON.parse(suid);
    //用户的全局唯一标识:事件id+个人id,中间以逗号隔开
    var user_guid = suid.data.su_id;
    ws_com.user_guid = user_guid;
    //初始化websocket
    if ('WebSocket' in window) {
        websocket = new WebSocket(wsUrl + user_guid);
    }
    websocket.onmessage = function(event) {
        var data = JSON.parse(event.data);
        if(data.type == "instructions"){
            if (data.content.indexOf(video_flag.play) > -1) {
                var time = data.content.split(video_flag.play)[1];
                video.play(time);
            } else if (data.content.indexOf(video_flag.pause) > -1) {
                var time = data.content.split(video_flag.pause)[1];
                video.pause(time);
            } else if (data.content.indexOf(video_flag.go_to) > -1) {
                var time = data.content.split(video_flag.go_to)[1];
                video.go_to(time);
            } else if (data.content.indexOf("eventChange") > -1) {
                //刷新页面数据  
                events.getEventsList();
            }else if (data.content.indexOf("wd_show") > -1) {
                //培训/演练切换
                $("#newShow").show();
                $("#wd").show();
            }else if (data.content.indexOf("wd_hide") > -1) {
                //培训/演练切换
                $("#newShow").hide();
                $("#wd").hide();
            }
        }else if(data.type == "message"){
            if(!($(this).hasClass('active'))) {
                communication.openWindow();
                $("#message").addClass("active");
                $(".message").css("visibility", "visible");
                $(".message").css("z-index",10);
            }
            //接收聊天内容
            var content = JSON.parse(data.content);
            ws_com.createRecord(content);
        }
    };

});

//阻止事件冒泡
$("#content_c").mousedown(function(e){
    if(e&&e.stopPropagation){//非IE
           e.stopPropagation();
          }
          else{//IE
           window.event.cancelBubble=true;
          }
});
$("#messAll").mousedown(function(e){
    if(e&&e.stopPropagation){//非IE
        e.stopPropagation();
    }
    else{//IE
        window.event.cancelBubble=true;
    }
});
$("#userList").mousedown(function(e){
    if(e&&e.stopPropagation){//非IE
        e.stopPropagation();
    }
    else{//IE
        window.event.cancelBubble=true;
    }
});

注意!!!
Tomcat7和8对于websocket的支持是不同的,以上代码是使用的Tomcat7,友情提示,避免踩坑

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值