Unity实现MQTT服务器
首先下载MqttNet:MqttNet下载地址
解压好后使用vs打开,并生成.dll文件(我这里下载的是4.1.2.350版本)
然后再/Source/MQTTnet/bin/Debug/net452 文件夹中找到生成的文件
新建unity工程,创建Plugins文件夹,将文件复制到该文件夹内
然后新建脚本MyMqttServer,代码内带有注释
using MQTTnet.Adapter;
using MQTTnet.Server;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MQTTnet;
using System.Threading.Tasks;
using System;
using System.Diagnostics.Tracing;
using System.Net;
using MQTTnet.Diagnostics;
using System.Text;
using MQTTnet.Protocol;
using static UnityEditor.ObjectChangeEventStream;namespace MQTT.Server
{/// <summary>/// 客户端信息/// </summary>public class MqttClientObject{public MqttClientObject(string clientID, string userName = "", string password = ""){this.ClientID = clientID;this.UserName = userName;this.PassWord = password;}public string ClientID { get; set; }public string UserName { get; set; }public string PassWord { get; set; }}/// <summary>/// MQTT服务/// </summary>public class MyMqttServer{/// <summary>/// 服务器对象/// </summary>private MqttServer m_MqttServer = null;/// <summary>/// Mqtt服务器选项生成器/// </summary>MqttServerOptionsBuilder optionbuilder = null;/// <summary>/// 连接的客户端/// </summary>private List<MqttClientObject> m_MqttClientObject = new List<MqttClientObject>();/// <summary>/// 开启服务器/// </summary>/// <param name="port"></param>public void StartMqttServer(int port = 1883){//1.创建服务器对象if (m_MqttServer == null){//创建Mqtt服务器选项生成器optionbuilder = new MqttFactory().CreateServerOptionsBuilder();//设置带有默认终端optionbuilder.WithDefaultEndpoint();//设置终端端口号optionbuilder.WithDefaultEndpointPort(port);//设置具有持续会话optionbuilder.WithPersistentSessions(true);//设置无默认通信超时optionbuilder.WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(60000));m_MqttServer = new MqttFactory().CreateMqttServer(optionbuilder.Build());}//监测服务器 开启/关闭m_MqttServer.StartedAsync += ServerStarted;m_MqttServer.StoppedAsync += ServerStoped;//监测客户端 连接/断开连接m_MqttServer.ClientConnectedAsync += ClientConnected;m_MqttServer.ClientDisconnectedAsync += ClientDisconnected;//监测客户端 订阅/取消订阅m_MqttServer.ClientSubscribedTopicAsync += ClientSubscribedTopic;m_MqttServer.ClientUnsubscribedTopicAsync += ClientUnSubscribedTopic;//客户端连接信息验证m_MqttServer.ValidatingConnectionAsync += ValidatingConnection;//获取客户端发送的消息m_MqttServer.InterceptingPublishAsync += InterceptingPublish;//开启服务器m_MqttServer.StartAsync();}/// <summary>/// 关闭服务/// </summary>public void StopMqttServer(){if (m_MqttServer != null){m_MqttServer.StopAsync();}}/// <summary>/// 获取服务器状态--开启/关闭/// </summary>/// <returns></returns>public bool GetMqttServerState(){if (m_MqttServer == null){return false;}return m_MqttServer.IsStarted;}/// <summary>/// 服务器完成开启/// </summary>/// <param name="eventArgs"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private Task ServerStarted(EventArgs eventArgs){Debug.Log("服务: started!");return Task.CompletedTask;}/// <summary>/// 服务器完成关闭/// </summary>/// <param name="eventArgs"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private Task ServerStoped(EventArgs eventArgs){Debug.Log("服务: stoped!");return Task.CompletedTask;}/// <summary>/// 客户端连接完成/// </summary>/// <param name="eventArgs"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private Task ClientConnected(ClientConnectedEventArgs eventArgs){Debug.Log($"服务:client Connected ClientId:{eventArgs.ClientId}");m_MqttClientObject.Add(new MqttClientObject(eventArgs.ClientId, eventArgs.UserName));return Task.CompletedTask;}/// <summary>/// 客户端订阅主题完成/// </summary>/// <param name="eventArgs"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private Task ClientSubscribedTopic(ClientSubscribedTopicEventArgs eventArgs){Debug.Log($"Client:{eventArgs.ClientId} -- Subscribed -- Topic:{eventArgs.TopicFilter.Topic}");ServerPublich(eventArgs.TopicFilter.Topic, $"Client:{eventArgs.ClientId} Subscribed this Topic");return Task.CompletedTask;}/// <summary>/// 客户端取消订阅主题完成/// </summary>/// <param name="eventArgs"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private Task ClientUnSubscribedTopic(ClientUnsubscribedTopicEventArgs eventArgs){Debug.Log($"Client:{eventArgs.ClientId} -- Subscribed -- Topic:{eventArgs.TopicFilter}");return Task.CompletedTask;}/// <summary>/// 客户端断开连接完成/// </summary>/// <param name="eventArgs"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private Task ClientDisconnected(ClientDisconnectedEventArgs eventArgs){Debug.Log($"Client:client DisConnected ClientId:{eventArgs.ClientId}");return Task.CompletedTask;}/// <summary>/// 客户端连接信息验证/// </summary>/// <param name="args"></param>/// <returns></returns>private Task ValidatingConnection(ValidatingConnectionEventArgs args){Debug.Log($"UserName:{args.UserName},PassWord:{args.Password}");return Task.CompletedTask;}/// <summary>/// 获取客户端发送的消息/// </summary>/// <param name="args"></param>/// <returns></returns>private Task InterceptingPublish(InterceptingPublishEventArgs args){Debug.Log($"Client:{args.ClientId} send Message : {Encoding.UTF8.GetString(args.ApplicationMessage.Payload)} -- Topic:{args.ApplicationMessage.Topic}");return Task.CompletedTask;}/// <summary>/// 服务器广播消息/// </summary>/// <param name="topic">主题</param>/// <param name="message">信息</param>public void ServerPublich(string topic, string message, bool isRetain = false, MqttQualityOfServiceLevel level = MqttQualityOfServiceLevel.ExactlyOnce){var builder = new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(message).WithRetainFlag(isRetain).WithQualityOfServiceLevel(level).Build();var data = new InjectedMqttApplicationMessage(builder);data.SenderClientId = "1";m_MqttServer.InjectApplicationMessage(data);}}
}
创建脚本MyMqttClient,代码内带有注释
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;/// <summary>
/// MQTT客户端
/// </summary>
public class MyMqttClient
{private IMqttClient m_MqttClient = null;private string m_ClientID;/// <summary>/// 创建客户端并连接服务器/// </summary>/// <param name="clientID"></param>/// <param name="ip"></param>/// <param name="port"></param>public MyMqttClient(string clientID, string ip = "127.0.0.1", int port = 1883){m_ClientID = clientID;//客户端选项生成器var options = new MqttClientOptionsBuilder().WithClientId(m_ClientID).WithTcpServer(ip, port).Build();//创建客户端m_MqttClient = new MqttFactory().CreateMqttClient();//监测客户端 连接/断开连接 完成m_MqttClient.ConnectedAsync += ClientConnected;m_MqttClient.DisconnectedAsync += ClientDisConnected;//客户端接收到消息m_MqttClient.ApplicationMessageReceivedAsync += ReceiveMsg;//连接服务器m_MqttClient.ConnectAsync(options);}/// <summary>/// 接收到消息/// </summary>/// <param name="args"></param>/// <returns></returns>private Task ReceiveMsg(MqttApplicationMessageReceivedEventArgs args){Debug.Log($"Receive Message From Client:{args.ClientId} msg:{Encoding.UTF8.GetString(args.ApplicationMessage.Payload)}");return Task.CompletedTask;}/// <summary>/// 断开连接完成/// </summary>/// <param name="args"></param>/// <returns></returns>private Task ClientDisConnected(MqttClientDisconnectedEventArgs args){Debug.Log("disConnected");return Task.CompletedTask;}/// <summary>/// 连接完成/// </summary>/// <param name="args"></param>/// <returns></returns>private Task ClientConnected(MqttClientConnectedEventArgs args){Debug.Log("connected");return Task.CompletedTask;}/// <summary>/// 发布消息/// </summary>public void PublishMsg(string topic, string message, MqttQualityOfServiceLevel level = MqttQualityOfServiceLevel.ExactlyOnce, bool isRetain = false){m_MqttClient.PublishStringAsync(topic, message, level, isRetain);}/// <summary>/// 订阅主题/// </summary>public void Subscribe(string topic){m_MqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());}
}
到这服务器与客户端脚本完成,接下来只需要写一些测试脚本,调用上面脚本的接口,即可完成服务器的开启/关闭,客户端连接,收发消息等功能。
相关文章:
Unity实现MQTT服务器
首先下载MqttNet:MqttNet下载地址 解压好后使用vs打开,并生成.dll文件(我这里下载的是4.1.2.350版本) 然后再/Source/MQTTnet/bin/Debug/net452 文件夹中找到生成的文件 新建unity工程,创建Plugins文件夹࿰…...
Linux(centos) 下 Mysql 环境安装
linux 下进行环境安装相对比较简单,可还是会遇到各种奇奇怪怪的问题,我们来梳理一波 安装 mysql 我们会用到下地址: Mysql 官方文档的地址,可以参考,不要全部使用 https://dev.mysql.com/doc/refman/8.0/en/linux-i…...
决策树(Decision Tree)
决策树的定义: 分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点(node)和有向边(directed edge)组成。结点有两种类型: 内部结点(internal node)和叶结点(leaf node࿰…...
解决 PaddleClas 下载预训练模型报错 ModuleNotFoundError No module named ‘ppcls‘ 的问题
当我们在使用 PaddleClas 进行预训练模型下载时,可能会遇到一个报错,报错信息为 ModuleNotFoundError: No module named ppcls。这个错误通常是因为 Python 解释器无法找到名为 ppcls 的模块,而我们的代码中正尝试导入它。让我们一起来解决这…...
视觉化洞察:为什么我们需要数据可视化?
为什么我们需要数据可视化?这个问题在信息时代变得愈发重要。数据,如今已成为生活的一部分,我们每天都在产生大量的数据,从社交媒体到购物记录,从健康数据到工作表现,数据无处不在。然而,数据本…...
C语言函数概述——拜佛代码
函数是一种可重用的代码块,用于执行特定任务或完成特定功能函数作用:对具备相同逻辑的代码进行封装,提高代码的编写效率,实现对代码的重用函数作用演示代码: #include <stdio.h>// 定义函数 void func() {print…...
防火墙日志分析工具
防火墙提供对进入组织网络的网络流量的来源和类型的可见性,这使得防火墙日志成为重要的信息源,包括所有连接的源地址、目标地址、协议和端口号等详细信息,此信息可以提供对未知安全威胁的见解,是威胁管理中的重要工具。 防火墙日…...
Autofac中多个类继承同一个接口,如何注入?与抽象工厂模式相结合
多个类继承同一个接口,如何注入?与抽象工厂模式相结合 需求: 原来是抽象工厂模式,多个类继承同一个接口。 现在需要使用Autofac进行选择性注入。 Autofac默认常识: Autofac中多个类继承同一个接口,默认是最后一个接口注入的类。 解决方案:(约定大于配…...
Django系列之日志配置
如何配置 settings.py 文件中增加如下日志模块 """logger 配置""" LOGGING {version: 1,disable_existing_loggers: False, # 是否去掉目前项目中其他地方中以及使用的日志功能,但是将来我们可能会引入第三方的模块,里…...
四轴飞行器传感器(SimulinkMatlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
学习 使用pandas库 DataFrame 使用
1 、 数据排序 sort_values()函数 by:要排序的名称或名称列表, sorted_df df.sort_values(byAge,ascendingFalse) 由大到小排序; sorted_df df.sort_values(byAge) 由小到大排序; # 创建一个示例数据帧 data {Name: [Tom, Nick, John…...
C++字符串详解
C 大大增强了对字符串的支持,除了可以使用C风格的字符串,还可以使用内置的 string 类。string 类处理起字符串来会方便很多,完全可以代替C语言中的字符数组或字符串指针。 string 是 C 中常用的一个类,它非常重要,我们…...
vant2 van-calendar组件增加清除按钮和确定按钮
利用自定义插槽增加一个清除按钮 <van-calendar ref"fTime1" select"selectTimePicker" confirm"changeTimePicker" :default-date"null" :show-confirm"false" v-model"timePickerShow" type"range&quo…...
Spring redis使用报错Read timed out排查解决
文章目录 使用场景报错信息解决方式 使用场景 我们使用redis作为缓存服务,缓存一些业务数据,如路口点位信息、渠化信息、设备信息等有一些需要实时计算的数据,缓存在redis里,如实时信号周期相位、周期内过车数量等有需要不同服务…...
C语言每日一练-------Day(9)
本专栏为c语言练习专栏,适合刚刚学完c语言的初学者。本专栏每天会不定时更新,通过每天练习,进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字:字符个数统计 多数元素 投票法 💓博主csdn个人主页…...
SpringCloud(十)——ElasticSearch简单了解(三)数据聚合和自动补全
文章目录 1. 数据聚合1.1 聚合介绍1.2 Bucket 聚合1.3 Metrics 聚合1.4 使用 RestClient 进行聚合 2. 自动补全2.1 安装补全包2.2 自定义分词器2.3 自动补全查询2.4 拼音自动补全查询2.5 RestClient 实现自动补全2.5.1 建立索引2.5.2 修改数据定义2.5.3 补全查询2.5.4 解析结果…...
二叉查找树(binary search tree)(难度7)
C数据结构与算法实现(目录) 答案在此:二叉查找树(binary search tree)(答案) 写在前面 部分内容参《算法导论》 基本接口实现 1 删除 删除值为value的第一个节点 删除叶子节点1 删除叶子节…...
windows环境装MailHog
背景:win10系统,windows 宝塔,laravel 项目,邮件相关需要装一个MailHog 下载地址:https://sourceforge.net/projects/mailhog.mirror/ 直接下载,下载后双击运行就可以了,系统可能提示”不信任“…...
Ubuntu 22.04.2 LTS 安装python3.6后报错No module named ‘ufw‘
查明原因: vim /usr/sbin/ufw 初步判断是python版本的问题。 # 查看python3软链接 ll /usr/bin/python3 将python3的软链接从python3.6换成之前的3.10,根据自己电脑情况。 可以查看下 /usr/bin 下有什么 我这是python3.10 所以解决办法是 # 移除py…...
Flutter小功能实现-咖啡店
1 导航栏实现 效果图: 1.Package google_nav_bar: ^5.0.6 使用文档: google_nav_bar | Flutter Package 2.Code //MyBottomNavBar class MyBottomNavBar extends StatelessWidget {void Function(int)? onTabChange;MyBottomNavBar({super.key, …...
Notepad2-mod终极指南:掌握这款高效开源文本编辑器的深度开发与扩展
Notepad2-mod终极指南:掌握这款高效开源文本编辑器的深度开发与扩展 【免费下载链接】notepad2-mod LOOKING FOR DEVELOPERS - Notepad2-mod, a Notepad2 fork, a fast and light-weight Notepad-like text editor with syntax highlighting 项目地址: https://gi…...
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前言 产品经理和开发之间的矛盾,根源往往不在需求本身,而在于需求表达方式。一个合格的需求文档应该包含:功能描述、业务规则、边界条件、异常处理、验收标准。但现实中,很多PRD长这样:“用户点击支付后,系…...
裁员风暴:从大厂骨干到失业边缘
2024年的春天,我在一家头部互联网公司担任测试主管的第八个年头,一场突如其来的裁员风暴打破了看似安稳的生活。公司战略收缩,测试部门首当其冲,我和近三成同事被列入优化名单。看着熟悉的工位被迅速清空,手里的离职证…...
SketchBook Pro 中文版
🎨 绘画爱好者必看!SketchBook Pro 中文破解版,让你的创意自由飞翔!✨ 👋 各位CSDN的小伙伴们,大家好呀~ 今天给大家带来一款超级好用的数字绘画神器—— SketchBook Pro 中文破解版!🎨🎨🎨 如果你是喜欢画画的、搞设计的、画概念图的,或者平时需要在电脑/平…...
Audio Slicer:智能音频分割终极指南,告别繁琐手动剪辑
Audio Slicer:智能音频分割终极指南,告别繁琐手动剪辑 【免费下载链接】audio-slicer A simple GUI application that slices audio with silence detection 项目地址: https://gitcode.com/gh_mirrors/aud/audio-slicer 还在为音频剪辑的繁琐操作…...
别再死记硬背二进制转换了!用Python写个自动转换工具,顺便搞懂CPU是怎么算的
用Python打造二进制转换工具:从代码实践理解CPU运算本质 当我们在编程中遇到需要处理二进制数据时,是否曾对背后的计算机原理产生好奇?本文将通过构建一个Python数制转换工具,带你穿透代码表层,深入理解CPU如何处理二…...
宇视出入口相机抓拍调试速成方法
宇视出入口相机抓拍调试速成方法一、背景概述智慧园区、停车场等场景已普及宇视出入口抓拍相机,用于车辆出入管控与车牌识别。现场易受光照、车速、车道环境等影响,常出现漏抓、识别率低、画面模糊等问题。传统调试无标准、耗时长、上手门槛高࿰…...
从一次失败的App上线,看我们如何用PDCA循环在3个月内实现用户留存翻倍
从一次失败的App上线,看我们如何用PDCA循环在3个月内实现用户留存翻倍 去年夏天,我们的团队经历了一次刻骨铭心的产品滑铁卢——一款投入半年研发的社交类App在上线首周就遭遇了用户留存率暴跌至8%的危机。这个数字远低于行业平均25%的水平线,…...
IPBan:企业级服务器安全防护解决方案的架构设计与实现
IPBan:企业级服务器安全防护解决方案的架构设计与实现 【免费下载链接】IPBan Since 2011, IPBan is the worlds most trusted, free security software to block hackers and botnets. With both Windows and Linux support, IPBan has your dedicated or cloud se…...
终极指南:如何用OpenHTMLtoPDF轻松生成专业级PDF文档
终极指南:如何用OpenHTMLtoPDF轻松生成专业级PDF文档 【免费下载链接】openhtmltopdf An HTML to PDF library for the JVM. Based on Flying Saucer and Apache PDF-BOX 2. With SVG image support. Now also with accessible PDF support (WCAG, Section 508, PDF…...
