WebSocket是一种在单个TCP连接上进行全双工通信的协议。
基于vite 搭建客户端环境:
环境搭建参考地址:https://cn.vitejs.dev/guide/
搭建好环境后在最外层添加vite.config.ts / vite.config.js 文件,文件内具体配置:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
// 配置依赖预构建, 只在生产环境中使用
optimizeDeps: {
include: process.env.NODE_ENV !== 'production' ? [] : ['antd', 'react'],
},
// 配置代理(处理跨域)
server: {
host: '0.0.0.0', // 主要是host这个配置,默认是localhost,修改为0.0.0.0之后,局域网内其他设备就可以访问了
port: 5173, // 设置服务启动端口号
cors: true, // 允许跨域
open: true, // 设置服务启动时是否自动打开浏览器
proxy: {
'/api': {
target: 'http://localhost:3001', // 目标服务器地址
changeOrigin: true, // 是否改变源地址
rewrite: (path) => path.startsWith('/') ? path : `/${path}` // 根据需要调整重写规则
}
}
}
})
在App.tsx中添加客户端逻辑:
- 添加前需先引用antd
import React, { FC, useEffect, useState } from 'react';
import { Form, Input, Button } from "antd";
const {TextArea } = Input;
const App: FC = () => {
const [form] = Form.useForm();
// 必须加 'ws://localhost:3001' ws 协议,后面是开启的服务端接口
const websocket = new WebSocket('ws://localhost:3001');
useEffect(() => {
// 打开事件
websocket.onopen = function () {
// 获取当前链接的状态
// 1 是建立了链接
console.log("onopen", websocket.readyState);
};
// 接收服务器返回的消息
websocket.onmessage = function (data) {
// 显示聊天内容的区域
const chatRoom = document.getElementById('chatRoom');
// 服务器返回过来的聊天信息
const chatS = JSON.parse(data.data);
// 添加到页面上
chatRoom.innerHTML += `
<strong>${chatS.userName}:</strong>
<span>${chatS.chatText}</span>
<br />
`
};
}, []);
// 提交表单
const onFinish = (values) => {
// 通过 websockte 发送消息
websocket.send(JSON.stringify(values));
form.setFieldsValue({ chatText: null}); // 清空对话框
};
// 随机生成一个昵称
const generateNickname = () => {
const adjectives = ['张', '王', '李', '赵', '刘', '朱', '左', '杨', '陈', '林', '彭', '毛', '郑', '高', '胡', '郭', '梅', '莫', '邓'];
const nouns = ['飞', '娜', '闪', '龙', '华', '宇', '杰', '强', '涛', '磊', '亮', '艺', '勇', '峰', '豪', '宏', '鹏', '琪', '婷', '丽', '洋'];
// 随机选择一个姓和一个名
const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
// 拼接成一个昵称
return randomAdjective + randomNoun;
};
// 客户端断开服务器连接 根据业务场景调用
// connection.on('close');
return (
<>
<div
id="chatRoom"
style={{
width: 600,
height: 400,
border: '1px solid #ccc',
overflowY: 'scroll',
marginBottom: "16px",
}}
></div>
<Form
layout="horizontal"
form={form}
style={{
maxWidth: 600,
}}
initialValues={{ userName: generateNickname() }}
onFinish={onFinish}
>
<Form.Item
label="用户名(临时模拟用户昵称)"
name="userName"
rules={[{ required: true }]}
>
<Input />
</Form.Item>
<Form.Item
label="对话框"
name="chatText"
rules={[{ required: true }]}
>
<TextArea placeholder="请输入对话内容" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
发送
</Button>
</Form.Item>
</Form>
</>
);
};
export default App;
Node 搭建服务端:
- npm init -y 初始化
- npm install ws 引用websocket
const websocket = require('websocket').server
const http = require('http');
const httpServer = http.createServer().listen(3001, () => {
console.log('Server is listening on port 3001: ', 'http://localhost:3001');
});
// 创建 websocket 服务器
const wsServer = new websocket({
httpServer: httpServer, // 绑定到http服务器
autoAcceptConnections: false, // 默认情况下接受所有连接
});
const conArr = []; // 存储所有连接(临时使用)
// 处理连接请求
wsServer.on('request', (request) => {
const connection = request.accept(); // 接受连接
console.log("connection", connection);
// 每次接收一个链接,将它存放在数组里面
conArr.push(connection);
// 监听消息
connection.on('message', (message) => {
// 广播消息
conArr.forEach((con) => {
// conArr[i].sendUTF(message.utf8Data); // 发送消息
con.send(message.utf8Data) // 发送消息
})
});
});
// 服务器断开连接,一般由客户端触发,服务端也可根据自身场景去决定是否关闭
// wsServer.onclose = function() {
console.log("关闭链接")
}