nodejs-websocket 實現單聊和群聊
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、伺服器端的程式碼可以先看
上面的使用方法。
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);
})
}