一、应用技术
使用 express + nodejs + websocket 技术,实现简单的聊天室实例
二、项目代码
1.使用express初始化一个项目
2.express 默认使用的是jade写页面,可以按找下面设置,就可以用熟悉的html或jsp
(1)安装ejs,命令 npm install ejs
(2)如下设置,就可以使用html页面了
3.写一个简单的聊天室页面
chat.html
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>聊天室</title>
</head>
<style>
input {
outline-style: none;
border: 1px solid #ccc;
border-radius: 3px;
padding: 13px 14px;
width: 620px;
font-size: 14px;
font-weight: 700;
font-family: "Microsoft soft";
margin: 20px;
}
input:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6)
}
span {
font-size: 24px;
font-weight: 700;
font-family: "Microsoft soft";
}
button {
width: 120px;
padding: 8px;
margin: 10px;
background-color: #428bca;
border-color: #357ebd;
color: #fff;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
/* future proofing */
-khtml-border-radius: 10px;
/* for old Konqueror browsers */
text-align: center;
vertical-align: middle;
border: 1px solid transparent;
font-weight: 900;
font-size: 100%
}
</style>
<body>
<h2>用户登录:</h2>
<input type="text" id='username' placeholder="请输入你的网名"><br>
<button id='confirm'>加入群聊</button>
<button id='closeWs'>退出群聊</button>
<br>
<h2>聊天内容:</h2>
<div id='talk' style='margin:20px;width:600px;height:400px;border:1px solid black;'>
</div>
<br>
<input type="text" id='message' placeholder="请输入聊天内容"><br>
<p>
<button id='sendBtn'>发送</button>
</p>
<div id='users' style="position: fixed;right:50px;top:20px;width:200px;height:200px;background: #00CCFF;">
<h4>在线人员:</h4>
</div>
</body>
<script type="text/javascript" src="../public/javascripts/chat.js"></script>
</html>
4. 编写JavaScript 文件,放到public/javascript下
chat.js
let ws = new WebSocket("ws://localhost:8181");
ws.onopen = function (e) {
console.log('Connection to server opened');
}
let userId = new Date().getTime();
// 关闭连接 删除用户
ws.onclose = function (e) {
console.log('Connection to server closed');
}
flag = false;
ws.onmessage = function (message) {
console.log("服务器返回的信息");
const state = message.data.slice(0, 1);//与服务器约定状态
const mes = message.data.slice(1);//聊天数据
if (state == 1) {
updateUserName(JSON.parse(mes))
}
console.log(state, mes);
}
function sendMessage() {
console.log(document.querySelector('#message').value)
// 发送
ws.send(document.querySelector('#message').value)
}
// 添加用户
document.querySelector('#confirm').addEventListener('click', () => {
console.log("11111", ws);
username = document.querySelector('#username').value
if (flag) return
// 修改信息,并且发送信息到服务器
let mess = {
id: userId,
name: username,
state: 1
}
flag = true
ws.send(JSON.stringify(mess))
})
// 更新用户表
function updateUserName(data) {
var parent = document.querySelector('#users')
// parent.innerHTML = ''
data.forEach((item) => {
var list = document.createElement('li')
list.innerHTML = item.name
parent.appendChild(list)
})
}
// 关闭连接事件
document.querySelector('#closeWs').addEventListener('click', () => {
// 取消用户信息
// 修改信息,并且发送信息到服务器
let mess = {
id: userId,
state: 4
}
ws.close(3000, JSON.stringify(mess));
window.location.reload();//退出之后,刷新页面
})
// 发送聊天信息
document.querySelector('#sendBtn').addEventListener('click', () => {// 发送
if (!flag) {
alert('请注册用户')
return
}
if (document.querySelector('#message').value != '' && flag) {
// 拼接数据
let mess = {
id: userId,
name: username,
state: 3,
time: new Date().toLocaleString(),
value: document.querySelector('#message').value
}
ws.send(JSON.stringify(mess))
document.querySelector('#message').value = ''
}
})
// 接受聊天信息
ws.onmessage = function (message) {
console.log('服务器返回的信息', message.data)
let state = message.data.slice(0, 1)
let data = JSON.parse(message.data.slice(1))
if (state == 1 || state == 4) {
updateUserName(data)
} else if (state == 3) {
updateTalkMessage(data)
}
}
// 更新聊天框信息
function updateTalkMessage(data) {
console.log(data)
var parent = document.querySelector('#talk')
var list = document.createElement('li')
list.innerHTML = `<strong>${data.time} ${data.name} 说</strong>: <font color="#FF0000">${data.value}</font>`
parent.appendChild(list)
}
5.添加路由,在routes下创建index.js,添加路由
var WebSocket = require('ws').Server;
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('chat', { WebSocket: WebSocket });
});
ps: 因为在javascript文件中使用require控制台报错,然后我选择把websocket当作参数,传递到页面中
6.添加websocket监听,我把文件放在/controller/下,也可自行选择
chat.js
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({ port: 8181 });
var users = [];
wss.on('connection', function (ws) {
console.log('client connected');
ws.on('message', function (message) {
message = JSON.parse(message)
console.log(message);
// 判断状态
if (message.state == 1) {
// 注册用户时间
users.push({
id: message.id,
name: message.name
})
} else if (message.state == 3) {
talkMessage = {
name: message.name,
time: message.time,
value: message.value
}
}
// 将更新的用户信息发送给所有用户
updateAllUsername(message.state)
});
ws.on('close', (state, msg) => {
// 通过id删除用户表
if (state == 3000) {
let id = JSON.parse(msg).id
users = users.filter((item) => {
return item.id !== id
})
}
// 给所有还在用的用户更新列表
updateAllUsername()
})
});
function updateAllUsername(state) {
let result = ''
if (state == 1 || state == 4) {
result = users
} else if (state == 3) {
result = talkMessage
}
for (let item of wss.clients) {
item.send(`${state}` + JSON.stringify(result))
}
}
7.启动服务, 如下
8.打开浏览器访问 127.0.0.1:3000
三、相关截图
退出
四、踩过的坑
在html页面直接引用public静态资源的时候,浏览器控制台报错,找不到对应的js文件。这时只需要在app中加入这行代码即可
五、项目地址
github: GitHub - luzai123/chat_server