nodejs 中使用websocket 并且区分空间,实现收到客服端消息 同步给房间内所有连接,小程序中使用websocket,区分房间、空间

这篇具有很好参考价值的文章主要介绍了nodejs 中使用websocket 并且区分空间,实现收到客服端消息 同步给房间内所有连接,小程序中使用websocket,区分房间、空间。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

❤️砥砺前行,不负余光,永远在路上❤️

前言

因为业务需要我这里是小程序 结合 nodejs来实现的websocket通信

一、服务端

1、主要是通过node+express+websocket搭建

2、代码大概结构

nodejs 中使用websocket 并且区分空间,实现收到客服端消息 同步给房间内所有连接,小程序中使用websocket,区分房间、空间

3、nodejs 启动入口文件 引入自己的websocket文件,这里是为了和 http 服务结合起来,将server传入

自己的文件中,http.createServer(app)
客户端那边就可以通过以下网址去访问了

ws://${IP}:3000/    // 3000也就是自己node启动的端口 另外 + 本机ip
const { port } = require('../config/index')
var app = require('../app');
var debug = require('debug')('projectname:server');
var http = require('http');
app.set('port', port);
var server = http.createServer(app);

try {
	const Websocket = require('../utils/websocket')(server)
} catch (error) {
	console.log(error);
}

4、websocket.js 工具文件完整代码

做个说明,这个是包含了我自己的部分业务需要,如果自己用不上数据库相关的东西可以删除,
我是在 headres 拿到token自己去去解析用户信息,还在headers 中携带了一个用户信息,
区分空间主要是在 连接websocket 的url上处理的,相同的房间请求同一个url,代码中也包含了详细注释。

/*
 * @Date: 2023-05-24 09:23:47
 * @LastEditTime: 2023-05-26 13:51:52
 */

const jwt = require('../utils/jwt')
const { literal, Op, Sequelize } = require("sequelize");
const { User, Room, RoomUser, Record, Standings } = require('../models/index')
const { uuid } = require('../utils/index');


const WebSocket = require('ws');
module.exports = function (server) {
	try {
		// 创建WebSocket服务器
		const wss = new WebSocket.Server({ server });
		// 管理连接和空间的数据结构
		const connections = new Map(); // 存储连接的Map,key为空间名称,value为连接数组

		// 监听连接事件
		wss.on('connection', async function connection (ws, req) {
			addToSpace(ws, req.url.split('/')[1]);
			console.log('New client connected', '------------------------------>');
			// 在这里可以访问 WebSocket 请求的请求头
			let { id } = jwt.verifyToken(req.headers.token);
			const roomId = req.headers['room-id']


			//通过 id去获取用户信息  / 不然可能用户更新了信息但是还是原来的token
			const res = await User.findOne({
				where: { id },
				raw: true,
			});
			//查看用户是否加入到房间
			let userIsJoin = await Record.findOne({
				where: { roomId, fromId: id, type: '2' },
				raw: true,
			});
			if (!userIsJoin) { //没有就加一个
				await Record.create({ id: uuid(), roomId, fromId: id, type: '2', createTime: Sequelize.fn('NOW') })
			}
			//有新的连接 也要下发信息
			console.log(`${res.nickName}加入了房间`, roomId);
			const data = { spaceName: req.url.split('/')[1], userJoin: `${res.nickName}加入了房间` }
			handleIncomingMessage(ws, JSON.stringify(data));

			// 监听消息接收事件
			ws.on('message', function incoming (message) {
				console.log('Received message:', message.toString('utf8'), '----------->', message);
				handleIncomingMessage(ws, message.toString('utf8'));
			});

			// 监听连接关闭事件
			ws.on('close', async function close () {
				console.log('Client disconnected');
				//查看用户是否加入到房间
				let userIsJoin = await Record.findOne({
					where: { roomId, fromId: id, type: '3' },
					raw: true,
				});
				if (!userIsJoin) { //没有就加一个
					await Record.create({ id: uuid(), roomId, fromId: id, type: '3', createTime: Sequelize.fn('NOW') })
				}

				const data = { spaceName: req.url.split('/')[1], userLeave: `${res.nickName}退出了房间` }
				handleIncomingMessage(ws, JSON.stringify(data));

				removeConnectionFromAllSpaces(ws);
			});
		});

		// 处理接收到的消息
		function handleIncomingMessage (ws, message) {
			const messageString = JSON.parse(message);
			// 假设消息格式为 "SPACE_NAME|MESSAGE_CONTENT"
			const { spaceName } = messageString
			// connection.send(content);
			const connectionsInSpace = connections.get(spaceName);
			if (connectionsInSpace) {
				// 向当前空间的所有连接发送消息
				connectionsInSpace.forEach(connection => {
					// if (connection == ws && connection.readyState === WebSocket.OPEN) {
					// 	console.log('send----------------------------');
					connection.send(JSON.stringify(messageString));
					// }
				});
			}
		}

		// 将连接添加到指定空间
		function addToSpace (ws, spaceName) {
			console.log(spaceName, '房间名称');
			let connectionsInSpace = connections.get(spaceName);
			if (!connectionsInSpace) {
				connectionsInSpace = new Set();
				connections.set(spaceName, connectionsInSpace);
			}
			connectionsInSpace.add(ws);
		}

		// 将连接从所有空间中移除
		function removeConnectionFromAllSpaces (ws) {
			connections.forEach(connectionsInSpace => {
				connectionsInSpace.delete(ws);
			});
		}
	} catch (error) {
		console.log(error);
	}
}

二、客户端部分

1、小程序在oonload中 连接websocket

onLoad(options) {
        console.log(options);
        const { roomNum, roomId } = options
        if (roomNum) {
                this.setData({ roomNum })
        }
        // this.getRoomInfo(wx.getStorageSync('roomId')) 这是拉取房间信息的接口  相当yu是在收到服务端消息之后自己去获取最新的信息
        this.connectWebSocket()  // 连接WebSocket服务器
},

2、this.connectWebSocket 代码和向服务器发送消息的代码如下

下面的WS_URL有标注。roomNum 就是房间编号是需要客户端这边确定 。
// WS_URL = ws://${IP}:3000/

/**
 * 连接WebSocket服务器
 */
connectWebSocket: function () {
        var _this = this
        wx.connectSocket({
                url: WS_URL + wx.getStorageSync('roomNum'),
                header: {
                        "token": wx.getStorageSync('token'),
                        "room-id": wx.getStorageSync('roomId'),
                },
                success: (res) => {
                        console.log('WebSocket连接成功:', res)
                        // wechatSIPlayAudio('WebSocket连接成功')
                        // _this.getRoomInfo(wx.getStorageSync('roomId'))
                },
                fail: function (res) {
                        console.log('WebSocket连接失败:', res)
                }
        })
        wx.onSocketOpen(function (res) {
                console.log('WebSocket连接已打开')
                _this.setData({ socketOpen: true })
        })
        wx.onSocketError(function (res) {
                console.log('WebSocket连接打开失败:', res)
        })
        wx.onSocketClose(function (res) {
                console.log('WebSocket连接已关闭:', res)
                _this.setData({
                        socketOpen: false
                })
        })
        wx.onSocketMessage(function (res) {
                //  收到服务器发送的数据之后  重新拉取 更新列表  
                const data = JSON.parse(res.data)
                console.log('接收到服务器发送的数据:', data)
                if (data.toId === wx.getStorageSync('userId')) {
                        getApp().util.toast(data.toMsg)
                        wechatSIPlayAudio(data.toMsg)
                        setTimeout(() => {
                                _this.getRoomInfo(wx.getStorageSync('roomId'))
                        }, 3000);
                } else {
                        _this.getRoomInfo(wx.getStorageSync('roomId'))
                }
                //用户加入 播报
                if (data.userJoin) {
                        wechatSIPlayAudio(data.userJoin)
                }

                //用户退出 播报
                if (data.userLeave) {
                        wechatSIPlayAudio(data.userLeave)
                }
        })
},
/**
 * 发送WebSocket消息
 */
sendSocketMessage: function (params) {
        if (this.data.socketOpen) {
                wx.sendSocketMessage({
                        data: JSON.stringify({
                                spaceName: wx.getStorageSync('roomNum'),
                                ...params
                        })
                })
        }
},

3、客户端说明

小程序这边逻辑 主要是在 收到服务端发送的消息之后去拉取最新的数据,来更新界面。文章来源地址https://www.toymoban.com/news/detail-469699.html

到了这里,关于nodejs 中使用websocket 并且区分空间,实现收到客服端消息 同步给房间内所有连接,小程序中使用websocket,区分房间、空间的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包