Socket.io+Nest:服务端和客户端实现

本教程记录使用 NestJS 和 socket.io 创建一个实时计数器模块,并提供客户端代码。用以备忘。

环境设置

  • npm

  • NestJS CLI

使用 NestJS CLI 创建一个新项目:

1npm i -g @nestjs/cli
2nest new realtime-counter
3cd realtime-counter

创建实时计数器模块

接下来,在 NestJS 项目中创建一个名为 CounterModule 的实时计数器模块,并使用 socket.io 实现。

安装依赖

realtime-counter 项目根目录下,安装所需的依赖:

1npm install @nestjs/platform-socket.io socket.io socket.io-client

编写代码

创建 CounterModule

src 目录下,创建一个名为 counter.module.ts 的新文件,并写入以下代码:

 1// src/counter.module.ts
 2import { Module } from '@nestjs/common';
 3import { SocketIoModule } from '@nestjs/platform-socket.io';
 4import { CounterGateway } from './counter.gateway';
 5
 6@Module({
 7  imports: [SocketIoModule.forRoot({})],
 8  providers: [CounterGateway],
 9})
10export class CounterModule {}

这里,我们使用 @nestjs/platform-socket.io@nestjs/websockets 包创建了一个 WebSocket 网关,即 CounterGateway。我们还将 CounterGateway 添加到 providers 数组中,以使它成为 NestJS 中的可注入对象。

创建 CounterGateway

同目录下,创建一个名为 counter.gateway.ts 的新文件,并写入以下代码:

 1// src/counter.gateway.ts
 2import {
 3  SubscribeMessage,
 4  WebSocketGateway,
 5  WebSocketServer,
 6  OnGatewayConnection,
 7} from '@nestjs/websockets';
 8import { Server, Socket } from 'socket.io';
 9
10@WebSocketGateway()
11export class CounterGateway implements OnGatewayConnection {
12  @WebSocketServer()
13  server: Server;
14
15  async handleConnection(client: Socket) {
16    let count = 0;
17    const interval = setInterval(() => {
18      count++;
19      client.emit('count', count);
20
21      if (count >= 25) {
22        clearInterval(interval);
23        client.disconnect(true);
24      }
25    }, 1000);
26  }
27
28  @SubscribeMessage('start')
29  handleMessage(client: Socket) {
30    client.emit('count', 0);
31  }
32}

这里,我们使用 @nestjs/websockets 包创建了一个 WebSocket 网关类 CounterGateway,它实现了 OnGatewayConnection 接口,用于处理客户端连接事件。

handleConnection 方法中,我们使用 setInterval 创建了一个计时器,它将每秒钟将 count

变量递增 1,并将 count 的值通过 client.emit 方法发送给客户端。在 count 达到 25 时,我们使用 clearInterval 方法停止计时器,并通过 client.disconnect(true) 方法断开客户端连接。

handleMessage 方法中,我们监听客户端的 start 事件,并通过 client.emit('count', 0) 方法向客户端发送一个初始值为 0 的 count

现在,我们已经完成了服务器端的代码。接下来,创建一个客户端来测试它。

创建客户端

在项目根目录下,创建一个名为 client.js 的文件,并写入以下代码:

 1// client.js
 2const io = require('socket.io-client');
 3const socket = io('http://localhost:3000');
 4
 5socket.on('connect', () => {
 6  console.log('Connected to the server');
 7  socket.emit('start');
 8});
 9
10socket.on('count', (count) => {
11  console.log('Current count:', count);
12});
13
14socket.on('disconnect', () => {
15  console.log('Disconnected from the server');
16  process.exit(0);
17});

这里,我们使用 socket.io-client 包创建了一个 WebSocket 客户端。在客户端连接到服务器时,我们通过 socket.emit('start') 向服务器发送一个 start 事件,以便服务器开始计数。

当服务器发送一个 count 事件时,我们通过 socket.on('count', (count) => {...}) 监听它,并将 count 的值打印到控制台上。

当客户端断开连接时,我们通过 socket.on('disconnect', () => {...}) 监听它,并输出一条相关的消息。

现在,我们已经完成了客户端的代码。接下来,启动服务器并运行客户端,以测试我们的实时计数器。

测试实时计数器

realtime-counter 项目根目录下,运行以下命令以启动 NestJS 服务器:

1npm run start

然后,在一个新的终端中,运行以下命令以运行客户端:

1node client.js

如果一切正常,你应该能够在客户端控制台上看到实时计数器输出。计数器将从 0 开始,每秒钟递增 1,直到计数器达到 25,然后客户端将断开连接。

添加错误处理逻辑

最后,我们可以在客户端代码中添加一些错误处理逻辑。以下是修改后的 client.js 文件,添加了处理连接错误和重连尝试的代码:

 1// client.js
 2const io = require('socket.io-client');
 3const socket = io('http://localhost:3000', {
 4  reconnectionAttempts: 5,
 5  timeout: 5000,
 6});
 7
 8socket.on('connect', () => {
 9  console.log('Connected to the server');
10  socket.emit('start');
11});
12
13socket.on('count', (count) => {
14  console.log('Current count:', count);
15});
16
17socket.on('connect_error', (error) => {
18  console.error('Connection error:', error.message);
19
20});
21
22socket.on('reconnecting', (attemptNumber) => {
23  console.log(`Attempting to reconnect (${attemptNumber})...`);
24});
25
26socket.on('reconnect_failed', () => {
27  console.error('Failed to reconnect. Exiting...');
28  process.exit(1);
29});
30
31socket.on('disconnect', () => {
32  console.log('Disconnected from the server');
33  process.exit(0);
34});

这里,我们在 io 构造函数的第二个参数中设置了 reconnectionAttemptstimeout 参数,用于指定客户端重连尝试的次数和超时时间。

当客户端无法连接到服务器或连接中断时,在客户端控制台上显示相关错误信息。同时,客户端将尝试重新连接服务器,最多尝试 5 次。如果所有重连尝试都失败,客户端将输出错误信息并退出。

现在,我们已经完成了实时计数器的 NestJS 模块和客户端代码。


本文由 GPT4 编写。