目录如下
?从上到下分别是node聊天服务,客户端代码,websocket封装类
代码文件如下
1.chatServer.js
let ws = require("nodejs-websocket");
process.stdin.setEncoding("utf8");
console.log("开始建立连接...");
let userObj = {};
let server = ws
.createServer(function (conn) {
conn.on("text", function (str) {
let newStr = eval("(" + str + ")");
const { memberId, targetId, content } = newStr;
console.log("收到的信息为:" + content);
console.log("用户id:" + memberId);
userObj[memberId] = {
coon: conn,
isOnline: true,
};
if (content !== "已经建立连接") {
//如果接收方在线
if (userObj[targetId]) {
userObj[targetId].coon.sendText(memberId + ":" + content);
}
conn.sendText(memberId + ":" + content);
}
//像前端页面发送推送
process.stdout.write("请输入发送的值:");
process.stdin.on("data", function (chunk) {
conn.sendText(chunk);
});
});
conn.on("close", function (code, reason) {
console.log("关闭连接");
});
conn.on("error", function (code, reason) {
console.log("异常关闭");
});
})
.listen(8801);
console.log("WebSocket建立完毕");
2.websocketClass.js
export default class Websocket {
static getInstance() {
if (!this.instance) {
this.instance = new websocket();
}
return this.instance;
}
constructor(props) {
this.instance = null;
this.heartConfig = {
timeout: 100000, //9分钟发一次心跳
};
this.ws = null;
this.lockReconnect = false;
this.wsUrl = null;
this.socketEventHandle = null;
}
//创建一个websocket
createWebSocket({ url, socketEventHandle }) {
let that = this;
that.wsUrl = url;
that.socketEventHandle = socketEventHandle;
try {
if ("WebSocket" in window) {
that.ws = new WebSocket(url);
} else if ("MozWebSocket" in window) {
that.ws = new MozWebSocket(url);
} else {
alert(
"您的浏览器不支持websocket协议,建议使用新版谷歌、火狐等浏览器,请勿使用IE10以下浏览器,360浏览器请使用极速模式,不要使用兼容模式!"
);
}
that.initEventHandle();
} catch (e) {
that.reconnect(url);
console.log(e);
}
}
//ws事件处理
initEventHandle() {
let that = this;
that.ws.onclose = function () {
that.reconnect(that.wsUrl);
console.log("ws连接关闭!" + new Date().toUTCString());
that.socketEventHandle({ type: "onclose" });
};
that.ws.onerror = function () {
that.reconnect(that.wsUrl);
console.log("ws连接错误!");
that.socketEventHandle({ type: "onerror" });
};
that.ws.onopen = function () {
that.heartCheck().reset().start(); //心跳检测重置
that.socketEventHandle({ type: "onopen" });
};
that.ws.onmessage = function (event) {
//如果获取到消息,心跳检测重置
that.heartCheck().reset().start(); //拿到任何消息都说明当前连接是正常的
that.socketEventHandle({ type: "sendMessage", message: event.data });
};
}
//重连
reconnect(url) {
let that = this;
if (that.lockReconnect) return;
that.lockReconnect = true;
setTimeout(function () {
//没连接上会一直重连,设置延迟避免请求过多
that.createWebSocket(url);
that.lockReconnect = false;
}, 2000);
}
//关闭连接
closeWebSocket() {
this.ws.close();
}
//发送消息
sendMessage(sendStr) {
this.ws.send(sendStr);
}
//心跳检查
heartCheck() {
let that = this;
//心跳检测
return {
timeout: 5 * 60 * 1000, //5分钟发一次心跳
timeoutObj: null,
serverTimeoutObj: null,
// ...that.heartConfig,
reset: function () {
var self = this;
clearTimeout(self.timeoutObj);
clearTimeout(self.serverTimeoutObj);
return self;
},
start: function () {
var self = this;
self.timeoutObj = setTimeout(function () {
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
that.ws.send("ping");
console.log("ping!");
self.serverTimeoutObj = setTimeout(function () {
//如果超过一定时间还没重置,说明后端主动断开了
that.ws.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
}, self.timeout);
}, self.timeout);
},
};
}
}
3.user.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>websocket(用户1)</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="col-sm-6">
<ul id="chat-list"></ul>
<div class="form-group">
<p></p>
<textarea id="chatBox" class="col-sm-2 form-control" rows="3" style="margin-bottom:10px"></textarea>
<button type="button" class="btn btn-primary" id="Bridge"
style="float: left;margin-right: 10px">建立连接</button>
<button type="button" id='btnSend' class="btn btn-success">发送信息</button>
</div>
</div>
</body>
<script type="module">
import Websocket from './websocketClass.js';
function getParam(url, name) {
try {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = url.split('?')[1].match(reg);
if (r != null) {
return r[2];
}
return "";//如果此处只写return;则返回的是undefined
} catch (e) {
return "";//如果此处只写return;则返回的是undefined
}
};
let memberId = getParam(window.location.href, 'memberId')
let targetId = getParam(window.location.href, 'targetId')
console.log('memberId', memberId, 'targetId', targetId)
let commonInfo = {
memberId,
targetId,
}
let myChatWs = new Websocket();
function createWebSocket() {
console.log('建立链接')
myChatWs.createWebSocket({
url: "ws://127.0.0.1:8801/",
socketEventHandle: socketEventHandle,
});
}
window.onload = function () {
document.querySelector("#btnSend").onclick = function (e) {
var chatBox = document.getElementById('chatBox').value;
let senObj = {
...commonInfo,
content: chatBox,
}
let sendStr = JSON.stringify(senObj)
myChatWs.sendMessage(sendStr);
document.getElementById('chatBox').value = '';
}
document.querySelector("#Bridge").onclick = function (e) {
createWebSocket()
}
}
function onopen() {
console.log("ws连接成功!" + new Date().toUTCString());
let senObj = {
...commonInfo,
content: "已经建立连接",
};
let sendStr = JSON.stringify(senObj);
myChatWs.sendMessage(sendStr);
document.getElementById("Bridge").style.display = "none";
}
function onMessageEventFun(message) {
console.log(message);
var li = document.createElement("li");
li.innerHTML = message;
if (message.indexOf(commonInfo.memberId) > -1) {
li.setAttribute(
"style",
"color: #E91E63;font-weight: 700;text-align: right;"
);
} else {
li.setAttribute("style", "color: #2196F3;font-weight: 700;");
}
document.getElementById("chat-list").appendChild(li);
}
function socketEventHandle({ type, message }) {
switch (type) {
case "onclose":
break;
case "onerror":
break;
case "onopen":
onopen();
break;
case "sendMessage":
onMessageEventFun(message);
break;
default:
break;
}
}
</script>
</html>
测试的时候先进入项目目录,命令行执行 node chatServer.js 开启node后台服务
下面两个是我这边对应的客服端两个需要链接的用户的地址。
http://127.0.0.1:5500/demo/user.html?memberId=1&targetId=2
http://127.0.0.1:5500/demo/user.html?memberId=2&targetId=1
|