nodejs-websocket 实现单聊和群聊

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CJXBShowZhouyujuan/article/details/77816944

nodejs-websocket 实现单聊和群聊

下载nodejs-websocket
https://github.com/sitegui/nodejs-websocket
最新公司有需求交给我一个任务,研究下关于websocket的即时通讯。写了一个在上面的基础上有优化了界面,也增加了功能
Demo地址
https://github.com/zhouyujuan/nodejs-websocket




使用nodejs-websocket的步骤
1、npm init 创建package.json
2、sudo npm install nodejs-websocket 就可以了
3、创建一个wsServer.js 是服务器文件
4、服务器端的代码可以先看https://github.com/sitegui/nodejs-websocket
上面的使用方法。
5、启动服务、node wsServer.js

wsServer.js 也就是服务器的代码

我们要先加载nodejs-websocket

var ws = require("nodejs-websocket")

// Scream server example: "hi" -> "HI!!!"
创建一个server
var server = ws.createServer(function (conn) {
    console.log("New connection")
接受到发送的消息
    conn.on("text", function (str) {
        console.log("Received "+str)
        conn.sendText(str.toUpperCase()+"!!!")
    })
关闭时触发的消息
    conn.on("close", function (code, reason) {
        console.log("Connection closed")
    })
}).listen(8001)

在服务端,接受到发起会话的消息时需要做很多的处理。判断会话所在的群组,判断会话对象的状态。等。
我在这里做的处理的思路
1、在chat界面发出了会话请求,这里会把发起会话人的基本信息整合成一个对象发送到服务器
// 连接成功建立的回调方法

    websocket.onopen = function(e) {
        // 建立连接后,要根据页面的url得知发起会话的人是想给谁发,或者在那个群里发
        var url = window.location.href;
        var splitobj = spliturl(url);
        user.name = splitobj.username;
        user.group = splitobj.groupnumber;
        if (user.group == undefined) {
            user.lineType = 1; //单聊
        } else {
            user.lineType = 0; //群聊
        }
        user.type = "enter";
        user.toname = splitobj.toname;
        websocket.send(JSON.stringify(user));
        // 这里是把发起会话的人的信息告诉服务器
        // 发送消息
        document.getElementById("sendBtn").onclick = function() {
            var txt = document.getElementById("sendText").value;
            document.getElementById('sendText').value = '';
            if (txt) {
                user.type = "message";
                user.data = txt;
                websocket.send(JSON.stringify(user));
            }
        }
    }

这里的信息包括了发起会话的人的
姓名(name)
发送给谁的(toname)这个在单聊的时候用到
群聊的id(group)群聊的id
发起会话的类型:(type)enter(进入)、 message(发消息)、leave(离开)

服务器接受到消息后

 var user;
    conn.on("text", function(str) {
        // 接收到客户端的消息时的处理
        // 这里的打印会在终端显示出来
        user = JSON.parse(str);
         // 这里相当于在有数据库情况下的一个查表的过程
         // 当有人在群里说话的时候,表示这个人是在线状态、
         // 这样他的好友在给他单独发消息的时候,发送的信息不回在这个群聊的会话列表展示
        if (user.group != undefined) {
            if (user.group == 1) {
                if (groups[0].members.contains(user.name)) {
                    console.log('可以进入群聊');
                    onlines.push(user.name);  //群聊的人在线状态的标识
                } else {
                    return;
                }
            } else if (user.group == 2) {
                if (groups[1].members.contains(user.name)) {
                    console.log('可以进入群聊');
                    onlines.push(user.name);
                } else {
                    return;
                }
            }
        } else {
            connections.push(user); // 如果不是群聊是单聊
        }

        // 当发起单聊的人超过1个人的时候,就要确定单聊的路线
        if (connections.length > 1) {
            for (var i = 0; i < connections.length; i++) {
                for (var j = i + 1; j < connections.length; j++) {
                    // 这里是判断单聊的路线,toname是要发送的人和要接受的人是否一样
                    if (connections[i].toname == connections[j].name &&
                        connections[j].toname == connections[i].name) {
                        signallines.push(connections[j].toname);
                        signallines.push(connections[j].name);

                    }
                }
            }
        }
       // 下面这些就是通过上面的信息,组织下要发送的信息

        var mes = {};
        mes.type = user.type;
        if (mes.type == 'enter') {
            mes.data = user.name;
        } else {
            mes.data = user.data;
        }
        mes.num = user.count;
        mes.name = user.name; //发起会话的人的姓名  这里最好使用id
        mes.toname = user.toname; //只会在单聊的时候存在,要发送给谁,也最好用id
        mes.groupnumber = user.group; //群聊的时候,群聊的id

        if (user.group != undefined) {
            // 你要单独给好友聊天,这里检测好友是否在群聊
            if (onlines.contains(mes.toname)) {
                console.log('我要发送的对象在线')
                 broadcast(JSON.stringify("好友在忙碌"));
            } else {
                broadcast(JSON.stringify(mes));
            }
        } else {
            // 你要单独给好友聊天,这里检测好友是否在和别人聊天
            if (signallines.contains(mes.toname) && signallines.contains(mes.name)) {
                broadcast(JSON.stringify(mes));
            } else {
                console.log('我要发送的---对象在线')
                broadcast(JSON.stringify("好友在忙碌"));       
            }
        }
        console.log('broadcast', JSON.stringify(mes));
    })

服务器接受到消息后。会判断这个会话是要在哪里发起(在群里,单聊的)
(1)如果带有群号,
验证下之后就可以吧这个user放到群聊在线的数组中(online)标识了一个状态;
(2)如果是单聊
放入单聊的数组中 connections.
对单聊的数组进行判断,如果大于两个人,我们需要在单聊的数组中找到配对的
也就是数组中一个对象A的toname 和 另一个对象B 的 name 相等 并且,B的toname和Aname相等。
这样就配对成功了

其实,这部分如果建了数据库处理起来很好,这里只是Dmeo所以没有做详尽的处理。

(3)通过(1)和(2)的操作我们基本知道了发起会话的人的应该 把他的会话转向哪里了
1、是转到那个群
2、是转到那个人哪里
3、还是告诉他好友在忙,无法发送消息

当会话关闭是

   conn.on("close", function(code, reason) {
        clientCount = 0;
        var mes = {}
        mes.type = "leave"
        mes.data = user.name + 'leave';
        // 离开群组或者离开单聊的时候,要把状态清空
        onlines.remove(user.name);
        connections.remove(user.name);
        signallines.remove(user.name);
        broadcast(JSON.stringify(mes))
    })

当离开的时候也清除记录,改变状态
发送消息的方法。

function broadcast(str) {
    console.log('str', str);
    // 取到server下面的所有连接
    server.connections.forEach(function(connection) {
        connection.sendText(str);
    })
}

猜你喜欢

转载自blog.csdn.net/CJXBShowZhouyujuan/article/details/77816944