NestJS Simple Chat - 分房(room)发送消息
更新日期 2022-5-11
开发环境
- macOS 12.3.1
- Ubuntu 16.04
- nest 8.1.5
- pm2 4.4.1
本文目的
- NestJS提供wss连接服务
- 引入房间(room)概念
- 用户加入房间后,收发同一个房间内的消息
主要使用的还是socketio的功能
gateway
使用之前创建的或者再新建一个Chat2Gateway
$ nest g gateway chat/chat2
要加入某个房间(room),使用join方法
socket.join(payload.room);
接收消息的时候,我们需要拿到socket
onJoin(socket: Socket, payload: any)
这里的socket用的是socket.io
里的
import { Socket } from 'socket.io';
服务对某个room进行群发消息,可以用to
指定房间
this.server.to(payload.room).emit('allMsg', payload);
Chat2Gateway
完整代码
| import { Logger } from '@nestjs/common';
import { OnGatewayInit, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Socket } from 'socket.io';
const opt2 = {
path: '/chat2',
allowEIO3: true,
cors: {
origin: /.*/,
credentials: true
}
};
@WebSocketGateway(opt2)
export class Chat2Gateway implements OnGatewayInit {
private logger: Logger = new Logger('Chat1Gateway');
@WebSocketServer()
server: any;
afterInit(server: any) {
this.server = server;
}
@SubscribeMessage('join')
onJoin(socket: Socket, payload: any): any {
socket.join(payload.room);
this.server.to(payload.room).emit('allMsg', payload);
}
@SubscribeMessage('message')
handleMessage(client: any, payload: any): any {
return {
event: 'message',
data: { code: 1, msg: "[chat2]服务 https://an.rustfisher.com" }
};
}
@SubscribeMessage('m2s')
onChatMsg(client: any, payload: any): any {
this.logger.log(payload);
var uid: String = payload.uid;
var roomId = payload.room;
if (uid != null && uid.length > 0) {
this.server.to(roomId).emit('allMsg', payload);
} else {
this.logger.warn('[m2s] 用户输入uid无效');
}
}
}
|
客户端(网页)
html
先来调整一下html,增加一些控件。用户可以输入room的id。
| <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Chat - an.rustfisher.com</title>
<link rel="stylesheet" href="/css/md.css" />
<script src="https://lib.baomitu.com/socket.io/4.4.1/socket.io.min.js"
crossorigin="anonymous"></script>
</head>
<body>
<h1>分房测试连接</h1>
<p>输入昵称和Room后再进行连接</p>
<div>
<label style="width: 200px;">昵称</label>
<input id="user-nickname"></input>
</div>
<div>
<label>Room</label>
<input id="room"></input>
</div>
<p>
<button class="btn" id="connect">Connect</button>
<button class="btn" id="leave">Leave</button>
</p>
<div>
<input placeholder="输入消息" id="user-input"></input>
<button class="btn" id="send">Send</button>
</div>
<ul id="msg-list">
</ul>
<script src="/js/chatroom.js"></script>
</body>
</html>
|
注意,html是用静态文件的方式来提供的。
css
增加一些样式
css
| .btn {
background-color: #225ece;
border: none;
border-radius: 2px;
color: white;
font-family: 'Roboto', sans-serif;
font-size: 0.8em;
margin: 0 0 1em 0;
padding: 0.5em 0.7em 0.6em 0.7em;
}
.btn:active {
background-color: #225ece;
}
.btn:hover {
background-color: #4372ca;
}
.btn[disabled] {
color: #ccc;
}
.btn[disabled]:hover {
background-color: #d84a38;
}
video {
background: #222;
margin: 0 0 20px 0;
--width: 100%;
width: var(--width);
height: calc(var(--width) * 0.75);
}
div#errorMsg p {
color: #F00;
font-size: small;
}
div#tipMsg p {
color: rgb(54, 54, 54);
font-size: small;
}
input {
color: #4372ca;
}
ul {
max-height: 200px;
overflow: auto;
}
li {
font-size: .3em;
}
|
js
连接上后,把room传给服务器。
| '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 roomIdInput = document.querySelector('input#room');
var msgList = document.querySelector('ul#msg-list');
var socket = null; // 连接
var uid = null;
var nickname = "RustFisher"; // 昵称
var roomId = "tmp-room1";
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 = "wss://antalkws.rustfisher.com" // release
socket = io(wssUrl, { path: '/chat2' });
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('join', {
uid: uid, nickname: userNicknameInput.value, room: getLocalRoomId(),
msg: '加入房间'
});
return true;
}
function disconnect() {
if (socket) {
socket.disconnect();
}
}
function getLocalRoomId() {
roomId = roomIdInput.value;
if (roomId == null || roomId.length == 0) {
console.warn('走默认room');
roomId = 'tmp-room1';
}
return roomId;
}
function sendMsg() {
var input = userInput.value;
roomId = roomIdInput.value;
if (input == null || input.length == 0) {
console.warn('请输入文本');
return;
}
if (roomId == null || roomId.length == 0) {
console.warn('走默认room');
roomId = 'tmp-room1';
}
if (socket) {
socket.emit('m2s',
{
uid: uid,
nickname: userNicknameInput.value,
room: roomId,
msg: input
});
}
}
btnConn.onclick = conn;
btnLeave.onclick = disconnect;
btnSend.onclick = sendMsg;
|
最后部署运行到服务器上
运行效果参考 chatroom - SimpleChat
示例工程 nest-sample - gitee
参考
建议详细读一下socket.io的文档 https://socket.io/docs/v4/emit-cheatsheet/ ,重点看Events部分
作者: rustfisher.com | rf.cs@foxmail.com
示例: AndroidTutorial Gitee, Tutorial Github
本文链接: https://www.an.rustfisher.com/nestjs/simple-chat/room-chat/
一家之言,仅当抛砖引玉。如有错漏,还请指出。如果喜欢本站的内容,还请支持作者。也可点击1次下方的链接(链接内容与本站无关),谢谢支持服务器