您的位置:首页 > Web前端 > Node.js

nodejs-websocket 实现单聊和群聊

2017-09-03 12:02 274 查看

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);
})
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息