WebSocket 连接前后端实现

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 连接

🔹 支持认证 / 断线重连 / 消息持久化

相关推荐
迅猛龙办公室5 小时前
Python输出当前计算机的系统日期和时间
开发语言·前端·python
小狼154545 小时前
浏览器扩展脚本为什么有时候不生效:注入时机、iframe 和单页路由,多多开票助手
前端·chrome
じòぴé南冸じょうげん5 小时前
油猴脚本突然发现变成灰色了,无法使用?页面不生效?刷新页面没反应?
前端
Csvn7 小时前
组合式 API(Composition API)
前端
火柴就是我8 小时前
Android 打包报错 25.0.3
android·前端
BD_Marathon8 小时前
消息对象中字段的说明
java·前端·python
八荒启·交互动画8 小时前
Web特效025—用 Canvas 2D 做Web特效的定义与边界:这支画笔能做到哪一步
前端·webgl·网页特效·八荒启-交互动画·八荒启
Ai-_Man8 小时前
您您这可以把Dola的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。用AI导出鸭,答案是可以的
开发语言·前端·人工智能·小程序
excel9 小时前
Nuxt 中使用 useHead 优化 SEO 与 GEO
前端
IT_陈寒10 小时前
SpringBoot启动慢得像蜗牛?原来是这个配置在捣鬼
前端·人工智能·后端