本地服务消息群发
更新日期 2022-5-19
- 2022-5-19 更新格式
- 2022-5-10 创建文档
将客户端(网页)发来的消息转发到其它已连接的客户端。
本地服务指的是在本机上运行服务。还没有将服务部署到服务器上。
gateway
我们继续改造Chat1Gateway
首先添加对状态的监听:OnGatewayInit
, OnGatewayConnection
, OnGatewayDisconnect
| import { OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Logger } from '@nestjs/common';
@WebSocketGateway(opt1)
export class Chat1Gateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
private logger: Logger = new Logger('Chat1Gateway');
@WebSocketServer()
server: any;
afterInit(server: any) {
this.server = server;
}
handleConnection(client: any, ...args: any[]) {
this.logger.log('新连接', args);
}
handleDisconnect(client: any) {
this.logger.log('断开了连接', client);
}
// ...
}
|
在afterInit
中,我们获取@WebSocketServer()
对象,后面用来群发消息。
监听m2s
事件,稍微判断一下发来的消息,然后将消息群发出去。
| @SubscribeMessage('m2s')
onChatMsg(client: any, payload: any): any { // 用户发来的消息 直接转发
var uid: String = payload.uid;
if (uid != null && uid.length > 0) { // (1)
this.server.emit('allMsg', payload);
}
}
|
- 这里对uid进行一个简单判断,具体根据实际情况来改
群发消息,使用server的emit
方法
this.server.emit('allMsg', payload);
Chat1Gateway完整代码
| import { OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Logger } from '@nestjs/common';
const opt1 = {
path: '/chat1',
allowEIO3: true,
cors: {
origin: /.*/,
credentials: true
}
};
@WebSocketGateway(opt1)
export class Chat1Gateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
private logger: Logger = new Logger('Chat1Gateway');
@WebSocketServer()
server: any;
afterInit(server: any) {
this.server = server;
}
handleConnection(client: any, ...args: any[]) {
this.logger.log('新连接', args);
}
handleDisconnect(client: any) {
this.logger.log('断开了连接', client);
}
@SubscribeMessage('debug')
handleMessage(client: any, payload: any): any { // 用来测试
this.logger.log('[debug]', payload);
return {
event: 'debug an.rustfisher.com',
data: payload
};
}
@SubscribeMessage('m2s')
onChatMsg(client: any, payload: any): any { // 用户发来的消息 直接转发
var uid: String = payload.uid;
if (uid != null && uid.length > 0) {
this.server.emit('allMsg', payload);
}
}
}
|
web
修改之前的页面,增加一些控件
html
加入2个input
,用来输入用户昵称和消息。
收到的消息放在msg-list
。
| <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Chat - an.rustfisher.com</title>
<link rel="stylesheet" href="/css/main.css" />
<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"
integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k"
crossorigin="anonymous"></script>
</head>
<body>
<h1>测试连接</h1>
<div>
<button id="connect">Connect</button>
<button id="leave">Leave</button>
</div>
<div>
<input id="user-nickname"></input>
<input id="user-input"></input>
<button id="send">Send</button>
</div>
<ul id="msg-list">
</ul>
<script src="/js/index.js"></script>
</body>
</html>
|
js
index.js完整代码如下
| 'use strict';
var btnConn = document.querySelector('button#connect');
var btnLeave = document.querySelector('button#leave');
var btnSend = document.querySelector('button#send');
var userNicknameInput = document.querySelector('input#user-nickname');
var userInput = document.querySelector('input#user-input');
var msgList = document.querySelector('ul#msg-list');
var socket = null; // 连接
var uid = null;
var nickname = "RustFisher"; // 昵称
var nameList = ["人参", "卜芥", "儿茶", "八角", "丁香", "刀豆", "三七", "大蓟", "山药", "川乌", "天冬", "天麻", "元胡"];
var nameIndex = Math.floor(Math.random() * nameList.length);
nickname = nameList[nameIndex]; // 随机昵称
userNicknameInput.value = nickname;
// 获取浏览器指纹
const fpPromise = import('https://openfpcdn.io/fingerprintjs/v3')
.then(FingerprintJS => FingerprintJS.load())
// Get the visitor identifier when you need it.
fpPromise
.then(fp => fp.get())
.then(result => {
// This is the visitor identifier:
uid = result.visitorId
const visitorId = result.visitorId
console.log(visitorId)
})
function addMsgToList(type, msgBody) {
var li = document.createElement("li");
li.setAttribute("id", "newli");
if (type == 0) {
li.innerHTML = msgBody;
} else if (type == 1) {
li.innerHTML = msgBody.nickname + ": " + msgBody.msg;
}
msgList.appendChild(li);
}
// 发起连接
function conn() {
if (uid == null) {
console.error('无法连接,还没获取到uid');
return;
}
console.log('try connect');
const wssUrl = "http://localhost:3000"; // localhost debug
socket = io(wssUrl, { path: '/chat1' });
socket.on('connect', function () {
console.log('连接成功');// 连接状态 连上
addMsgToList(0, '连接成功');
});
socket.on('disconnect', (socket) => {
console.log('socket已断开', socket);// 连接状态 已断开
socket = null;
});
socket.on('debug', (data) => {
console.log('[服务器消息][debug], ', data);
});
socket.on('allMsg', (data) => {
console.log('[服务器消息][allMsg], ', data);
addMsgToList(1, data);
});
socket.emit('debug', { uid: uid, msg: "web连接" });
return true;
}
function disconnect() {
if (socket) {
socket.disconnect();
}
}
function sendMsg() {
var input = userInput.value;
if (input == null || input.length == 0) {
console.warn('请输入文本');
return;
}
if (socket) {
socket.emit('m2s',
{
uid: uid,
nickname: userNicknameInput.value,
msg: input
});
}
}
btnConn.onclick = conn;
btnLeave.onclick = disconnect;
btnSend.onclick = sendMsg;
|
用FingerprintJS
来获取浏览器的信息。可随机产生一些默认的昵称,也可以由用户来输入。
收到服务器消息后,用document.createElement
方式添加到列表中。
一些连接状态信息也添加到了消息列表中。
发送消息时,用emit
方法,把uid,nickname,msg都传上去。
测试运行
运行NestJS服务后,我们可以用2个浏览器或者2个页面,直接打开index.html,点击connect连接。
然后输入要发送的消息,在其他页面上可以看到效果。
营造出一种类似多人聊天室的感觉。
网页效果

参考
示例工程 nest-sample - gitee
作者: rustfisher.com | rf.cs@foxmail.com
示例: AndroidTutorial Gitee, Tutorial Github
本文链接: https://www.an.rustfisher.com/nestjs/simple-chat/transfer-msg-local/
一家之言,仅当抛砖引玉。如有错漏,还请指出。如果喜欢本站的内容,还请支持作者。也可点击1次下方的链接(链接内容与本站无关),谢谢支持服务器。
如有疑问,请与我联系:Android issues - gitee