WebSocket 连接前后端实现(详细示例)
WebSocket 适用于 实时通信 场景,如即时聊天 、在线状态 、通知推送 等。下面是完整的 前后端 WebSocket 连接示例 ,包括 Node.js(Egg.js / NestJS)后端 和 React / Vue 前端。
🔵 1. 后端(Node.js)WebSocket 实现
后端可以使用 WebSocket Server 处理连接、消息收发、断线重连等逻辑。这里提供 Egg.js 和 NestJS 两种方案。
方案 1:Egg.js WebSocket
Egg.js 官方提供了 @eggjs/plugin-websocket
插件,适用于 WebSocket 连接管理。
(1)安装 WebSocket 插件
lua
npm install egg-socket.io --save
(2)配置 WebSocket
编辑 config/plugin.ts
,启用 socket.io
:
arduino
export default {
io: {
enable: true,
package: 'egg-socket.io',
},
};
编辑 config/config.default.ts
:
arduino
export default {
io: {
namespace: {
'/chat': {
connectionMiddleware: ['auth'], // 可选:认证中间件
packetMiddleware: ['filter'], // 可选:数据过滤
},
},
},
};
(3)实现 WebSocket 逻辑
新建 app/io/controller/chat.ts
:
javascript
import { Controller } from 'egg';
export default class ChatController extends Controller {
async connect() {
const { ctx, app } = this;
const socket = ctx.socket;
const { id } = socket; // 获取 socket ID
console.log(`🔗 用户已连接: ${id}`);
// 监听消息
socket.on('message', async (data) => {
console.log(`📩 收到消息: ${data}`);
// 发送给所有连接的客户端
app.io.of('/chat').emit('message', data);
});
// 监听断开
socket.on('disconnect', () => {
console.log(`❌ 用户断开连接: ${id}`);
});
}
}
(4)注册 WebSocket 事件
在 app/io/middleware/auth.ts
添加身份验证:
javascript
export default async (ctx, next) => {
const { socket } = ctx;
const token = socket.handshake.query.token; // 获取前端传递的 token
console.log(`🔑 认证 Token: ${token}`);
if (!token || token !== 'VALID_TOKEN') {
return socket.disconnect(); // 认证失败,断开连接
}
await next();
};
方案 2:NestJS WebSocket
NestJS 提供了 @nestjs/websockets
处理 WebSocket 连接。
(1)安装 WebSocket 依赖
bash
npm install @nestjs/websockets @nestjs/platform-socket.io
(2)创建 WebSocket 网关
新建 chat.gateway.ts
:
typescript
import { WebSocketGateway, SubscribeMessage, MessageBody, OnGatewayConnection, OnGatewayDisconnect, WebSocketServer } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat', cors: true }) // 开启跨域
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer() server: Server;
handleConnection(client: Socket) {
console.log(`🔗 用户连接: ${client.id}`);
}
handleDisconnect(client: Socket) {
console.log(`❌ 用户断开: ${client.id}`);
}
@SubscribeMessage('message')
handleMessage(@MessageBody() message: string): void {
console.log(`📩 收到消息: ${message}`);
this.server.emit('message', message); // 广播消息
}
}
(3)注册 WebSocket
在 app.module.ts
中注册 ChatGateway
:
python
import { Module } from '@nestjs/common';
import { ChatGateway } from './chat.gateway';
@Module({
providers: [ChatGateway],
})
export class AppModule {}
🟡 2. 前端 WebSocket 连接
前端可以使用 socket.io-client
或原生 WebSocket
进行通信。
方案 1:React WebSocket(使用 socket.io-client)
(1)安装 socket.io-client
lua
npm install socket.io-client
(2)创建 WebSocket 连接
新建 useWebSocket.ts
Hook:
javascript
import { useEffect, useState } from 'react';
import { io } from 'socket.io-client';
const SOCKET_URL = 'http://localhost:7001/chat';
export default function useWebSocket() {
const [socket, setSocket] = useState(null);
const [messages, setMessages] = useState<string[]>([]);
useEffect(() => {
const newSocket = io(SOCKET_URL, {
query: { token: 'VALID_TOKEN' }, // 认证 Token
});
newSocket.on('connect', () => console.log('✅ 已连接 WebSocket'));
newSocket.on('message', (msg) => {
console.log('📩 收到消息:', msg);
setMessages((prev) => [...prev, msg]);
});
setSocket(newSocket);
return () => newSocket.close(); // 组件卸载时断开连接
}, []);
return { socket, messages };
}
(3)在 React 组件中使用
javascript
import useWebSocket from './useWebSocket';
export default function Chat() {
const { socket, messages } = useWebSocket();
const [input, setInput] = useState('');
const sendMessage = () => {
if (socket && input) {
socket.emit('message', input);
setInput('');
}
};
return (
<div>
<h1>💬 聊天</h1>
<ul>
{messages.map((msg, i) => (
<li key={i}>{msg}</li>
))}
</ul>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button onClick={sendMessage}>发送</button>
</div>
);
}
方案 2:Vue WebSocket(使用 socket.io-client)
(1)安装 socket.io-client
lua
npm install socket.io-client
(2)创建 WebSocket 连接
新建 useWebSocket.js
:
javascript
import { ref, onMounted, onUnmounted } from 'vue';
import { io } from 'socket.io-client';
const SOCKET_URL = 'http://localhost:7001/chat';
export default function useWebSocket() {
const messages = ref([]);
let socket;
onMounted(() => {
socket = io(SOCKET_URL, { query: { token: 'VALID_TOKEN' } });
socket.on('message', (msg) => {
console.log('📩 收到消息:', msg);
messages.value.push(msg);
});
});
const sendMessage = (msg) => {
if (socket) socket.emit('message', msg);
};
onUnmounted(() => {
if (socket) socket.close();
});
return { messages, sendMessage };
}
(3)在 Vue 组件中使用
xml
<template>
<div>
<h1>💬 聊天</h1>
<ul>
<li v-for="(msg, i) in messages" :key="i">{{ msg }}</li>
</ul>
<input v-model="input" />
<button @click="sendMessage(input)">发送</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import useWebSocket from './useWebSocket';
const { messages, sendMessage } = useWebSocket();
const input = ref('');
</script>
总结
🔹 Egg.js / NestJS 实现 WebSocket 后端
🔹 React / Vue 实现 WebSocket 前端连接
🔹 socket.io
方便管理 WebSocket 连接
🔹 支持认证 / 断线重连 / 消息持久化