服务端实现
1. 安装依赖
npm install express express-ws
2. 创建 Express 应用并集成 WebSocket
const express = require('express');
const expressWs = require('express-ws');
const app = express();
expressWs(app);
// 连接进来的所有客户端
const clients = new Set();
// websocket 接口
app.ws('/socketTest', (ws, req) => {
console.log('origin',req.host);
const { host } = req;
clients.add(ws);
console.log('客户端已连接,当前连接数:', clients.size);
// 监听客户端发送的消息
ws.on('message', (message) => {
console.log('收到消息:', message);
// 广播消息给所有客户端
broadcast(message);
});
// 监听连接关闭事件
ws.on('close', () => {
console.log('客户端断开连接,当前连接数:', clients.size - 1);
clients.delete(ws);
});
});
// 广播消息函数
function broadcast(message) {
for (const client of clients) {
if (client.readyState === 1) { // WebSocket.OPEN
client.send(message);
}
}
}
//监听端口3001
app.listen(3001, () => {
console.log('Server running on port 3001');
});
客户端实现
建立一个socket.js文件
//socket.js
const socket = new WebSocket('ws://172.16.1.249:3001/socketTest');
socket.onopen = () => {
console.log('socket 服务连接成功');
}
socket.onmessage = (event) => {
console.log('收到消息:', event.data);
}
socket.onclose = () => {
console.log('Disconnected from server');
}
socket.onerror = (error) => {
console.error('Error:', error);
}
export default socket;
使用socket
import { useState } from "react";
import { Input,Button,Flex } from "antd";
import socket from '../../hooks/useWS'
const {TextArea } = Input;
export default function Home() {
const [inputValue, setInputValue] = useState('');
const [messageData, setMessageData] = useState([])
socket.onmessage = (event) => {
const res = JSON.parse(event.data)
setMessageData([...messageData,res]);
}
const handleChange = (e) => {
setInputValue(e.target.value);
};
const handleClick = () => {
const res = {
userName: window.location.host,
message: inputValue
}
socket.send(JSON.stringify(res));
};
return (
<>
<Flex>
<TextArea value={inputValue} onChange={handleChange} placeholder="Basic usage" />
</Flex>
<Button type="primary" onClick={handleClick}>发送</Button>
{
messageData.length ? messageData.map((item,index) => {
return <div key={index}>{`${item.userName}:${item.message}`}</div>
}):''
}
</>
);
}
页面效果
启两个前端页面端口为3000、3002
3000页面
发信息“哈哈哈”、“i am a good boy”
3002页面
发消息“你是”、“?”