react前端自己实现websocket聊天室

240 阅读1分钟

服务端实现

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”

image.png

3002页面

发消息“你是”、“?”

image.png