使用NestJs提供WebSocket服务。

本文会在新建项目的基础上增加2个类

  • Gateway 实现业务逻辑的地方
  • WebSocketAdapter WebSocket适配器

新建项目

新建一个项目来演示,用npm来管理项目。

nest new websocket-start

得到一个有基础功能的工程。

进入项目目录,安装2个库

npm i --save @nestjs/websockets @nestjs/platform-socket.io

启动

使用端口3001

await app.listen(3001);

npm run start启动我们的工程。用postman测一下,功能ok。

gateway介绍

Nest里的gateway(网关)只是一个用 @WebSocketGateway() 装饰器注释的类。从技术上讲,网关与平台无关,在创建适配器后它们与任何 WebSockets 库都兼容。

新建Gateway

新建ws.gateway.ts文件。在装饰器@WebSocketGateway()里端口指定为3002。

import { ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway } from "@nestjs/websockets";
import * as WebSocket from 'ws'; @WebSocketGateway(3002)
export class WsStartGateway { @SubscribeMessage('hello')
hello(@MessageBody() data: any): any {
return {
"event": "hello",
"data": data,
"msg": 'rustfisher.com'
};
}
}

里面有一个hello方法,订阅的消息是'hello'

把它放进AppModuleproviders里。

providers: [WsStartGateway],

如果websockt和http用了同一个接口(本例是3001),启动时会报错

Error: listen EADDRINUSE: address already in use :::3001

因此我们这里给ws分配另一个端口号。

获取WebSocket对象

WsStartGateway里新增加一个消息订阅方法。

方法里接受@ConnectedSocket() client: WebSocket,这个client就是与客户端的连接对象。

我们可以用它来给客户端发送消息。

  @SubscribeMessage('hello2')
hello2(@MessageBody() data: any, @ConnectedSocket() client: WebSocket): any {
console.log('收到消息 client:', client);
client.send(JSON.stringify({ event: 'tmp', data: '这里是个临时信息' }));
return { event: 'hello2', data: data };
}

自定义WebSocketAdapter

前面我们建立好了Gateway,还需要一个适配器。

新建文件ws.adapter.ts,继承WebSocketAdapter

import * as WebSocket from 'ws';
import { WebSocketAdapter, INestApplicationContext } from '@nestjs/common';
import { MessageMappingProperties } from '@nestjs/websockets';
import { Observable, fromEvent, EMPTY } from 'rxjs';
import { mergeMap, filter } from 'rxjs/operators'; export class WsAdapter implements WebSocketAdapter { constructor(private app: INestApplicationContext) { } create(port: number, options: any = {}): any {
console.log('ws create')
return new WebSocket.Server({ port, ...options });
} bindClientConnect(server, callback: Function) {
console.log('ws bindClientConnect, server:\n', server);
server.on('connection', callback);
} bindMessageHandlers(
client: WebSocket,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
) {
console.log('[waAdapter]有新的连接进来')
fromEvent(client, 'message')
.pipe(
mergeMap(data => this.bindMessageHandler(client, data, handlers, process)),
filter(result => result),
)
.subscribe(response => client.send(JSON.stringify(response)));
} bindMessageHandler(
client: WebSocket,
buffer,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
): Observable<any> {
let message = null;
try {
message = JSON.parse(buffer.data);
} catch (error) {
console.log('ws解析json出错', error);
return EMPTY;
} const messageHandler = handlers.find(
handler => handler.message === message.event,
);
if (!messageHandler) {
return EMPTY;
}
return process(messageHandler.callback(message.data));
} close(server) {
console.log('ws server close');
server.close();
}
}

bindMessageHandler方法中,会将传来的json消息解析,然后发送到对应的处理器中。

这里就是发给gateway进行处理。

判断依据是message.event,就是event字段。

main.ts里使用这个适配器。

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from './ws/ws.adapter'; async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useWebSocketAdapter(new WsAdapter(app)); // 使用我们的适配器
await app.listen(3001);
}
bootstrap();

npm run start运行项目,准备进一步测试。

用Postman来测试WebSocket

Postman8.8.0提供了beta版的WebSocket测试功能。

New -> WebSocket Request beta新建一个WebSocket测试。当前版本还不支持保存ws的测试例子。

输入目标url ws://localhost:3002,点击连接 Connect 按钮。

发送测试消息。在消息框里填入以下json数据。

{
"event" : "hello",
"data" : "测试数据"
}

发送的数据经过WsAdapter分发给WsStartGateway,处理后返回数据。

发送hello2测试数据

{
"event" : "hello2",
"data" : "测试数据"
}

可以看到服务返回了2条数据。

发送一个错误格式的数据

{
"event" : "hello2

服务端接收到了数据,但是解析失败

ws解析json出错 SyntaxError: Unexpected end of JSON input

小结

要使用WebSocket功能,需要增加

  • Gateway 实现业务逻辑的地方
  • WebSocketAdapter WebSocket适配器

ws的端口建议是和http的端口分开。

参考

NestJS WebSocket 开始使用的更多相关文章

  1. 漫扯:从polling到Websocket

    Http被设计成了一个单向的通信的协议,即客户端发起一个request,然后服务器回应一个response.这让服务器很为恼火:我特么才是老大,我居然不能给小弟发消息... 轮询 老大发火了,小弟们自 ...

  2. 细说WebSocket - Node篇

    在上一篇提高到了 web 通信的各种方式,包括 轮询.长连接 以及各种 HTML5 中提到的手段.本文将详细描述 WebSocket协议 在 web通讯 中的实现. 一.WebSocket 协议 1. ...

  3. java使用websocket,并且获取HttpSession,源码分析

    转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...

  4. WebSocket - ( 一.概述 )

    说到 WebSocket,不得不提 HTML5,作为近年来Web技术领域最大的改进与变化,包含CSS3.离线与存储.多媒体.连接性( Connectivity )等一系列领域,而即将介绍的 WebSo ...

  5. php+websocket搭建简易聊天室实践

    1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...

  6. Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!

    随着HTML5 WebSocket技术的日益成熟与普及,我们可以借助WebSocket来更加方便地打通BS与CS -- 因为B/S中的WebSocket可以直接连接到C/S的服务端,并进行双向通信.如 ...

  7. Cowboy 开源 WebSocket 网络库

    Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...

  8. 借助Nodejs探究WebSocket

    文章导读: 一.概述-what's WebSocket? 二.运行在浏览器中的WebSocket客户端+使用ws模块搭建的简单服务器 三.Node中的WebSocket 四.socket.io 五.扩 ...

  9. 细说websocket - php篇

    下面我画了一个图演示 client 和 server 之间建立 websocket 连接时握手部分,这个部分在 node 中可以十分轻松的完成,因为 node 提供的 net 模块已经对 socket ...

随机推荐

  1. C语言真正的编译过程

    说实话,很多人做了很久的C/C++,也用了很多IDE,但是对于可执行程序的底层生成一片茫然,这无疑是一种悲哀,可以想象到大公司面试正好被问到这样的问题,有多悲催不言而喻,这里正由于换工作的缘故,所以打 ...

  2. Etcd中Raft joint consensus的实现

    Joint consensus 分为2个阶段,first switches to a transitional configuration we call joint consensus; once ...

  3. 剑指 Offer 05. 替换空格

    链接:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/ 标签:字符串 题目 请实现一个函数,把字符串 s 中的每个空格替换成"%2 ...

  4. NX二次开发】Block UI 选择特征

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  5. 【VBA】延时函数

    延时函数(单位秒),例如延时0.5秒 1 Sub 延时() 2 delay (0.5) 3 Debug.Print "延时0.5秒" 4 End Sub 5 6 Sub delay ...

  6. Jenkins+Github+Nginx实现前端项目自动部署

    前言 最近在搭建一个自己的网站,网站框架搭好了要把项目放到服务器运行,但是每次更新网站内容就要手动部署一次,实在很麻烦,于是就想搭建一套自动化部署的服务.看了一些案例最后选用现在比较主流的Jenkin ...

  7. 老公 今晚还玩“丝袜哥”Swagger 么?

    大家都知道Swagger是一个常用的Spring Boot接口文档生成工具,但是我们今天再介绍另外一个无需额外注解的 Spring Boot API文档生成神器,非常方便好用! JApiDocs是一个 ...

  8. npm ERR! Unexpected end of JSON input while parsing near '...'解决方法

    npm install时出现npm err! Unexpected end of JSON input while parsing near'...'错误 输入  npm cache clean -- ...

  9. CosId 1.0.0 发布,通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

  10. 什么IP欺骗?

    1.什么是IP欺骗? IP欺骗是指创建源地址经过修改的Internet协议(IP) 数据包,目的要么是隐藏发送方的身份,要么是冒充其他计算机系统,或者两者兼具.恶意用户往往采用这项技术对目标设备或周边 ...