Nestjs教程使用Socket.IO实现实时消息推送

我在使用NestJS结合Socket.IO实现实时消息推送时遇到了一些问题。首先不太清楚如何在NestJS中正确配置Socket.IO模块,官方文档的说明比较简略。其次,我在客户端连接时总是出现404错误,不知道是不是网关配置有问题。另外想请教如何区分不同类型的实时消息,比如私聊和群聊消息该如何通过Socket.IO实现?最后,想了解在生产环境中如何优化Socket.IO的性能,比如是否需要Redis适配器?希望有经验的大佬能分享一下具体实现方案和最佳实践。

3 回复

首先安装必要的依赖:

npm install @nestjs/websockets socket.io
  1. 创建一个WebSocket服务模块:
nest g module chat
nest g service chat/chat
nest g controller chat/chat
  1. chat.service.ts中配置Socket.IO
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Server, Socket } from 'socket.io';

@Injectable()
export class ChatService implements OnModuleInit {
  private server: Server;
  private clients = new Map();

  onModuleInit() {
    this.server = new Server();
    this.server.on('connection', (socket: Socket) => {
      console.log(`Client connected: ${socket.id}`);
      this.clients.set(socket.id, socket);

      socket.on('disconnect', () => {
        this.clients.delete(socket.id);
        console.log(`Client disconnected: ${socket.id}`);
      });
    });
  }

  // 广播消息
  broadcastMessage(message: string) {
    this.clients.forEach((client) => client.emit('message', message));
  }
}
  1. chat.controller.ts中设置路由:
import { Controller, Get, OnModuleInit } from '@nestjs/common';
import { Server, Socket } from 'socket.io';
import { ChatService } from './chat.service';

@Controller()
export class ChatController implements OnModuleInit {
  constructor(private readonly chatService: ChatService) {}

  onModuleInit() {
    this.chatService.server.installHandlers(this);
  }

  @Get('broadcast')
  broadcastMessage(@Query('message') message: string) {
    this.chatService.broadcastMessage(message);
    return { success: true };
  }
}
  1. 最后在主应用文件main.ts中启用WebSocket:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Server } from 'socket.io';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const server = app.getHttpAdapter().getInstance();
  const io = new Server(server);

  io.on('connection', (socket) => {
    console.log(`Client connected: ${socket.id}`);
  });

  await app.listen(3000);
}
bootstrap();

启动应用后,访问/broadcast?message=HelloWorld即可广播消息。


要在NestJS中使用Socket.IO实现实时消息推送,首先安装必要的依赖:

npm install @nestjs/websockets socket.io
  1. 创建一个WebSocket服务:
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { WsGateway } from './ws.gateway';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, WsGateway],
})
export class AppModule {}
  1. 定义WebSocket网关:
// ws.gateway.ts
import { WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway()
export class WsGateway {
  @WebSocketServer() server: Server;

  afterInit(server: Server) {
    console.log('WebSocket初始化完成');
  }

  handleConnection(client: Socket) {
    console.log(`客户端已连接: ${client.id}`);
  }

  handleDisconnect(client: Socket) {
    console.log(`客户端断开连接: ${client.id}`);
  }

  sendMessageToClient(message: string) {
    this.server.emit('message', message);
  }
}
  1. 调用发送消息:
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { WsGateway } from './ws.gateway';

@Controller()
export class AppController {
  constructor(private readonly wsGateway: WsGateway) {}

  @Get('send-message')
  async sendMessage() {
    this.wsGateway.sendMessageToClient('Hello, Client!');
    return '消息已发送!';
  }
}

这样就完成了简单的实时消息推送功能。客户端通过socket.on('message', callback)接收消息。

NestJS中使用Socket.IO实现实时消息推送教程

基本设置

  1. 首先安装Socket.IO相关依赖:
npm install @nestjs/platform-socket.io socket.io @types/socket.io
  1. 创建Socket.IO网关(Gateway):
import { SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway({
  cors: {
    origin: '*', // 设置允许的客户端来源
  },
})
export class EventsGateway {
  @WebSocketServer()
  server: Server;

  afterInit(server: Server) {
    console.log('Socket.IO服务器已初始化');
  }

  handleConnection(client: Socket) {
    console.log(`客户端已连接: ${client.id}`);
  }

  handleDisconnect(client: Socket) {
    console.log(`客户端已断开连接: ${client.id}`);
  }

  @SubscribeMessage('message')
  handleMessage(client: Socket, payload: any): string {
    console.log('收到消息:', payload);
    this.server.emit('message', payload); // 广播给所有客户端
    return '消息已接收';
  }
}
  1. 在AppModule中注册网关:
import { Module } from '@nestjs/common';
import { EventsGateway } from './events.gateway';

@Module({
  providers: [EventsGateway],
})
export class AppModule {}

高级功能实现

  1. 实现房间功能:
@SubscribeMessage('joinRoom')
handleJoinRoom(client: Socket, room: string): void {
  client.join(room);
  console.log(`客户端 ${client.id} 加入了房间 ${room}`);
}

@SubscribeMessage('leaveRoom')
handleLeaveRoom(client: Socket, room: string): void {
  client.leave(room);
  console.log(`客户端 ${client.id} 离开了房间 ${room}`);
}

// 向特定房间发送消息
sendToRoom(room: string, event: string, message: any) {
  this.server.to(room).emit(event, message);
}
  1. 在服务中使用Socket.IO
import { Injectable } from '@nestjs/common';
import { EventsGateway } from './events.gateway';

@Injectable()
export class ChatService {
  constructor(private readonly eventsGateway: EventsGateway) {}

  sendMessageToAll(message: string) {
    this.eventsGateway.server.emit('message', message);
  }
}

客户端连接

前端HTML示例:

<script src="https://cdn.socket.io/4.3.1/socket.io.min.js"></script>
<script>
  const socket = io('http://localhost:3000');
  
  socket.on('connect', () => {
    console.log('已连接到服务器');
  });
  
  socket.on('message', (data) => {
    console.log('收到消息:', data);
  });
  
  function sendMessage() {
    const message = document.getElementById('message').value;
    socket.emit('message', message);
  }
</script>

这就是在NestJS中使用Socket.IO实现实时消息推送的基本方法。你可以根据需求扩展更多功能,如用户认证、消息持久化等。

回到顶部