前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Chat</title>
</head>
<style>
/* 可选样式,注释掉的div样式可以控制显示区域的大小和边框 */
/*
div {
width: 300px;
height: 300px;
border: 1px solid #000;
overflow: auto; /* 允许内容溢出时出现滚动条 */
}
*/
</style>
<body>
<!-- 输入框用于输入消息 -->
<input type="text" placeholder="请输入你的消息">
<!-- 按钮用于发送消息 -->
<button>发送请求</button>
<!-- 显示消息的区域 -->
<div></div>
<script>
// 定义消息类型的常量
const TYPE_ENTER = 0 // 用户进入
const TYPE_LEAVE = 1 // 用户离开
const TYPE_MSG = 3 // 普通消息
// 选择 HTML 元素
var inpt = document.querySelector('input') // 获取输入框元素
var button = document.querySelector('button') // 获取按钮元素
var div = document.querySelector('div') // 获取用于显示消息的 div 元素
// 创建一个 WebSocket 连接,ws:// 是 WebSocket 的协议
var socket = new WebSocket('ws://localhost:3000')
// 当 WebSocket 连接成功打开时触发的事件
socket.addEventListener('open', function () {
div.innerHTML = '连接打开' // 在页面上显示连接打开的消息
})
// 当用户点击发送按钮时触发
button.addEventListener('click', function () {
var value = inpt.value // 获取输入框中的文本
socket.send(value) // 将文本通过 WebSocket 发送到服务器
inpt.value = '' // 清空输入框
})
// 当接收到 WebSocket 消息时触发
socket.addEventListener('message', function (e) {
var data = JSON.parse(e.data) // 将收到的数据(JSON格式)解析成对象
console.log(e.data) // 在控制台打印收到的消息
var dv = document.createElement('div') // 创建一个新的 div 元素
dv.innerText = data.msg + ' ---- ' + data.time // 将消息和时间显示在 div 中
// 根据消息的类型设置不同的颜色
if(data.type === TYPE_ENTER) {
dv.style.color = 'green' // 进入时,消息显示为绿色
} else if(data.type === TYPE_LEAVE) {
dv.style.color = 'red' // 离开时,消息显示为红色
} else {
dv.style.color = 'blue' // 普通消息显示为蓝色
}
div.appendChild(dv) // 将新创建的 div 元素添加到显示消息的区域
})
// 当 WebSocket 连接关闭时触发
socket.addEventListener('close', function () {
div.innerHTML = '连接关闭' // 在页面上显示连接关闭的消息
})
</script>
</body>
</html>
后端配置
// 导入 nodejs-websocket 模块,用于创建 WebSocket 服务器
const ws = require('nodejs-websocket')
// 定义服务器监听的端口
const PORT = 3000
// 定义消息类型的常量
const TYPE_ENTER = 0 // 用户进入消息
const TYPE_LEAVE = 1 // 用户离开消息
const TYPE_MSG = 3 // 普通聊天消息
/*
消息结构:
1. type:消息的类型(进入、离开、普通消息)
2. msg:消息内容
3. time:消息发送的具体时间
*/
// 创建 WebSocket 服务器,每次有用户连接时都会产生一个 conn 对象
let count = 0 // 用于统计连接的用户数
const serve = ws.createServer(conn => {
console.log('有新的连接');
count++ // 用户数加1
conn.userName = `用户${count}` // 给新用户分配用户名
// 广播新用户加入的消息给所有人
broadcast({
type: TYPE_ENTER, // 消息类型:进入
msg: `${conn.userName} 加入了聊天室`, // 消息内容
time: new Date().toLocaleTimeString() // 发送时间
});
// 监听用户发送的消息
conn.on('text', data => {
console.log('收到消息:', data);
// 广播用户的消息给所有人
broadcast({
type: TYPE_MSG, // 消息类型:普通消息
msg: data, // 用户发送的消息内容
time: new Date().toLocaleTimeString() // 发送时间
});
})
// 监听连接关闭事件
conn.on('close', () => {
console.log(`${conn.userName} 断开了连接`);
count-- // 用户数减1
// 广播用户离开的消息给所有人
broadcast({
type: TYPE_LEAVE, // 消息类型:离开
msg: `${conn.userName} 离开了`, // 消息内容
time: new Date().toLocaleTimeString() // 发送时间
});
})
// 监听错误事件
conn.on('error', (err) => {
console.log('连接异常:', err); // 记录错误
})
})
// 广播消息给所有连接的用户
function broadcast(msg) {
// 遍历所有连接的用户并发送消息
serve.connections.forEach(conn => {
conn.send(JSON.stringify(msg)) // 将消息对象转成 JSON 字符串发送
})
}
// 服务器开始监听指定端口
serve.listen(PORT, () => {
console.log(`服务器启动了,监听端口 ${PORT}`);
})