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

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

相关推荐
小小坤14 分钟前
前端基于AI生成H5 vue3 UI组件
前端·javascript·vue.js
既见君子29 分钟前
透明视频
前端
竹等寒32 分钟前
Go红队开发—web网络编程
开发语言·前端·网络·安全·web安全·golang
lhhbk36 分钟前
angular中下载接口返回文件
前端·javascript·angular·angular.js
YUELEI11841 分钟前
Vue使用ScreenFull插件实现全屏切换
前端·javascript·vue.js
我自纵横20231 小时前
第一章:欢迎来到 HTML 星球!
前端·html
发财哥fdy1 小时前
3.12-2 html
前端·html
ziyu_jia1 小时前
React 组件测试【React Testing Library】
前端·react.js·前端框架
祈澈菇凉2 小时前
如何在 React 中实现错误边界?
前端·react.js·前端框架
撸码到无法自拔2 小时前
❤React-组件的新旧生命周期
前端·javascript·react.js·前端框架·ecmascript