nodejs+koa2+pm2+ws开发聊天室 (仿微信网页版界面)
https://blog.csdn.net/qq_42783610/article/details/85233555 先看我之前的博客配置koa2脚手架 #项目使用的是纯html代码的ejs
https://blog.csdn.net/qq_42783610/article/details/85233415 配置pm2 windows开机自启动项目 , #这里可以不配置
配置完后:
cd进入目录
执行npm install mongodb --save #保存用户登录信息,可以不使用数据库,自己判断用户
npm install ws --save #安装ws包
先更改bin/www:
var http = require('http');
var app = require('../app');
var server = http.createServer(app.callback());
//改成
var server = require('../app');//让http创建在app.js
服务器端的逻辑
const WebSocket = require('ws');
//末尾添加
const server = http.createServer(app.callback()) //创建http
const wss = new WebSocket.Server({server}) //创建ws
global.userList = []; //用户登录状态
wss.on('connection',(ws)=>{
ws.on('message',async (msg) => { //监听客户端发送消息
const data = JSON.parse(msg);
if (util.search(userList,data.user_id)) { //判断是否有这个人了,避免刷新页面添加用户
userList.push(data.user_id)
}
let _id = mongodb.getObjectID(data.user_id);
let find = await mongodb.find('user',{_id}) //查询用户信息
if (data.check == 0) { //有人进入,就给所有人发送进来的信息,并添加至客户端的侧边栏
let id = userList.indexOf(data.user_id)
Array.from(wss.clients).forEach((value,index) => {
if (id == index) { //给进来的那个人发送所有人的信息
userList.map(async(value,index) => {
let _id = mongodb.getObjectID(value);
let finds = await mongodb.find('user',{_id})
Array.from(wss.clients)[id].send(JSON.stringify({ //返回用户信息
"user_id": `${finds[0].user_id}`,
"check":`${data.check}`,
"user_num":`${userList.length}`
}))
})
}else { //给其他人发送,有人进来的信息,并添加至客户端的侧边栏
Array.from(wss.clients)[index].send(JSON.stringify({
"user_id": `${find[0].user_id}`,
"check":`${data.check}`,
"user_num":`${userList.length}`
}))
}
})
}else if (data.check == 2 ) { //发送用户说的话
let id = userList.indexOf(data.user_id);
Array.from(wss.clients).forEach((value,index) => { //自己发的,在客户端显示右边
if (id == index) {
Array.from(wss.clients)[index].send(JSON.stringify({ //过滤xss
"user_id": `${find[0].user_id}`,
"data":`${data.msg.replace(/[<">']/g, (a) => {
return {
'<': '<',
'"': '"',
'>': '>',
"'": '''
}[a]
})}`,
"check":`${data.check}`,
"who":'1'
}))
}else { //别人发的,在客户端显示左边
Array.from(wss.clients)[index].send(JSON.stringify({
"user_id": `${find[0].user_id}`,
"data":`${data.msg.replace(/[<">']/g, (a) => {
return {
'<': '<',
'"': '"',
'>': '>',
"'": '''
}[a]
})}`,
"check":`${data.check}`,
"who":'2'
}))
}
})
}
ws.on('close',() => { //监听客户端断开链接
util.remove(userList,data.user_id) //退出从列表中删除
wss.clients.forEach(function each(client){
client.send(JSON.stringify({
"user_id": `${find[0].user_id}`,
"check":"1",
"user_num":`${userList.length}` //从客户端侧边栏删除,并返回人数
}))
})
})
})
})
module.exports = server
客户端的逻辑:
<!DOCTYPE html>
<html>
<head>
<title>
chatRoom
</title>
<link rel='stylesheet' href='/css/style.css' />
<link rel='stylesheet' href='/css/index.css' />
</head>
<body>
<div class="wrapper">
<div class="index">
<div class="main">
<div class="main_inner">
<div class="main_left">
<ul id="num"> <!--这里是侧边栏-->
</ul>
</div>
<div class="main_right">
<div class="top">
chatRoom 在线人数:<span id="user_num"></span>
</div>
<div class="content">
<div class="noinfo">
暂无消息
</div>
<div id="info">
</div>
</div>
<div class="insert">
<textarea name="name" rows="8" cols="80" id="input"></textarea>
<button type="button" name="button" id="send">发送</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bg"></div>
</body>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
$(()=>{
let ws = new WebSocket('ws://localhost:3000') //连接
let user_id = sessionStorage.user_id;
ws.onopen = () => { //连上后操作
console.log(`[CLIENT] open()`)
if (user_id) { //检测session(登录状态)是否有效
$.ajax({
method:'get',
url:'../checkSession',
data:{
user_id:sessionStorage.user_id
},
success:res => {
if (res.errCode == 0) {
ws.send(JSON.stringify({
"user_id": `${user_id}`,
"check":"0"
}))
}
},
error:err => {
if (err.responseJSON.errCode == 1) {
location.replace('/')
}
}
})
}else {
location.replace('/')
}
function send(event){ //发送给服务器端
if (event.keyCode && event.keyCode!= 13) { //回车发送
return;
}
if ($('#input').val()) {
ws.send(JSON.stringify({
"user_id": `${user_id}`,
"msg": `${$('#input').val()}`,
"check":"2"
}))
$('#input').val('') //发送后重置
}
}
$('#send').on('click', send)//绑定事件
$('#input').on('keyup',send)
}
ws.onmessage = (chunk) => {
const msg = JSON.parse(chunk.data);
if (msg.check == 0) { //侧边栏添加 有用户进来
$("#num").append(`<li>${msg.user_id}</li>`)
$("#user_num").text(msg.user_num)
}else if (msg.check == 1) { //侧边栏删除 有用户离开
$("#num li:contains("+msg.user_id+")").remove()
$("#user_num").text(msg.user_num)
}else if(msg.check == 2){ //获取聊天内容
let date = new Date();
let hour = date.getHours();
let min = date.getMinutes();
$('#info').css('display','block')
$('.noinfo').css('display','none') //把默认显示暂无消息去除
if (sessionStorage.hour && hour - sessionStorage.hour >= 1 || sessionStorage.min && min - sessionStorage.min == 10) { //一段时间后发送显示时间
sessionStorage.hour = hour
sessionStorage.min = min
$("#info").append(`<div class="time">${hour}:${min < 10 ? min = '0'+min : min}</div>`);
}else if(!sessionStorage.hour || !sessionStorage.min){
sessionStorage.hour = hour
sessionStorage.min = min
$("#info").append(`<div class="time">${hour}:${min < 10 ? min = '0'+min : min}</div>`);
}
if (msg.who == 1) { //判断是自己发送的还是别人送的,自己在右,别人在左
$("#info").append(`<div class='say'><div id='data'> <span>${msg.data}</span></div><img src= 'images/tou.jpg'> <p>${msg.user_id}</p></div>`)
}else {
$('#info').append(`<div class="ysay"> <img src="images/tou.jpg" alt=""><p>${msg.user_id}</p> <div id="data2"><span>${msg.data}</span></div></div>`)
}
$("#info").scrollTop($('#info').get(0).scrollHeight) //若内容超出显示滚动条,并使滚动条一直在底部
}
}
ws.onclose = () => {
console.log('server close')
}
ws.onerror = (err) => {
console.log(err);
}
})
</script>
</html>
github完整项目地址https://github.com/MRXKing/chatRoom