NestJS WebSocket 开始使用
使用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'
。
把它放进AppModule
的providers
里。
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 WebSockets https://docs.nestjs.com/websockets/gateways
- NestJS 合集 https://rustfisher.com/categories/NestJS/
- 示例工程 https://gitee.com/rustfisher/nest-sample
NestJS WebSocket 开始使用的更多相关文章
- 漫扯:从polling到Websocket
Http被设计成了一个单向的通信的协议,即客户端发起一个request,然后服务器回应一个response.这让服务器很为恼火:我特么才是老大,我居然不能给小弟发消息... 轮询 老大发火了,小弟们自 ...
- 细说WebSocket - Node篇
在上一篇提高到了 web 通信的各种方式,包括 轮询.长连接 以及各种 HTML5 中提到的手段.本文将详细描述 WebSocket协议 在 web通讯 中的实现. 一.WebSocket 协议 1. ...
- java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...
- WebSocket - ( 一.概述 )
说到 WebSocket,不得不提 HTML5,作为近年来Web技术领域最大的改进与变化,包含CSS3.离线与存储.多媒体.连接性( Connectivity )等一系列领域,而即将介绍的 WebSo ...
- php+websocket搭建简易聊天室实践
1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...
- Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!
随着HTML5 WebSocket技术的日益成熟与普及,我们可以借助WebSocket来更加方便地打通BS与CS -- 因为B/S中的WebSocket可以直接连接到C/S的服务端,并进行双向通信.如 ...
- Cowboy 开源 WebSocket 网络库
Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...
- 借助Nodejs探究WebSocket
文章导读: 一.概述-what's WebSocket? 二.运行在浏览器中的WebSocket客户端+使用ws模块搭建的简单服务器 三.Node中的WebSocket 四.socket.io 五.扩 ...
- 细说websocket - php篇
下面我画了一个图演示 client 和 server 之间建立 websocket 连接时握手部分,这个部分在 node 中可以十分轻松的完成,因为 node 提供的 net 模块已经对 socket ...
随机推荐
- C++中头文件和实现文件的关系
头文件相当于是声明的集合,包括头文件的语句#Include实质为程序代码的宏替换. 编译阶段将函数和变量登记在符号表,链接时将各种函数的入口地址在其中查找到来调用,解引用.
- .NET平台系列22:.NET Core/.NET5/.NET6 对比 .NET Framework
系列目录 [已更新最新开发文章,点击查看详细] 在我的博客<.NET平台系列2 .NET Framework 框架详解>与 <.NET平台系列7 .NET Core 体系结构 ...
- Git与GitHub入门
一.git起步https://www.runoob.com/git/git-install-setup.html1.下载git(Windows)2.安装GUI(TortoiseGit)3.查看git配 ...
- ld-linux-x86-64消耗大量的CPU
1.现象: 服务器CPU使用率很高 top查看cpu使用进程: 2.进程用户是oracle,根据spid查看是否是数据库进程,经过查询发现:不是数据库内部的进程 select a.sql_id,a.s ...
- k8s通过ceph-csi接入存储的概要分析
kubernetes ceph-csi分析目录导航 概述 下面的分析是k8s通过ceph-csi(csi plugin)接入ceph存储(csi相关组件的分析以rbd为例进行分析),对csi系统结构. ...
- 入门Kubernetes - 滚动升级/回滚
一.前言 上一篇文章中对yaml文件格式进行了解,并对k8s中各种主要资源通过yaml创建时的定义模板.接来下就进一步学习k8s的各种特点.并应用在示例中. 接下来先实现.Net Core Api程序 ...
- js jquey 笔记
1.使用insertAfter 如果插入在tr后添加多行数据,数据会倒过来注意组字符串需要倒着循环 1).html方法,给元素添加html代码或者清空html代码(参数为空字符串): 2).appen ...
- 资源:Maven相关jar快速下载地址
Maven下载海外jar包太慢,可以进入下面地址搜索下载 下载地址:https://www.findjar.com/
- 解决ionic5多个模态关闭一个其他不显示的问题
ionic5 modal使用过程中,在模态窗中打开另外一个模态窗,浏览器中显示正常,但是andorid8系统真机调试时,关闭最上层模态窗,上级模态窗DOM中存在,但是不显示. 原因是android版本 ...
- cut和grep 选取命令
cut命令 cut:将一段信息的某一段"切"出来,处理的信息是以行为单位.参数: -d :后接分隔字符,与-f一起使用: -f :依据-d的分隔字符将一段信息切割成为数段,用-f取 ...