C#实现MQTT over WebSocket

如何在网页端实现MQTT消息的发布和订阅?

  • 实现MQTT功能,可以发布和订阅主题
  • 通过WebSocket协议将MQTT消息转发给对应的网页端

带着这个实现思路,采用C#控制台程序实现MQTT服务端功能,web端可以直接使用websocket插件与服务端双向通讯。

  1. 新建C#控制台程序,.net framework框架版本4.5.2
  2. 引用Fleck框架,版本1.2.0
  3. 引用MQTTnet框架,版本4.3.1.873

1、WebSocket功能实现

socketDic 字典key值记录每个客户端,value记录每个客户端对应的SN,代表设备的序列号;

每当有网页端客户端连接的时候,自动将客户端套接字加入字典中;

每当网页关闭,服务端自动断开客户端套接字连接,并从缓存字典中移除此客户端套接字;

当网页端客户端套接字发送包含SN:开头的字符,表示网页端发送了设备的SN,服务端接收此消息,并解析设备SN,并与对应的客户端套接字绑定对应关系,在缓存字典中维护对应关系。

class Server
{static Dictionary<IWebSocketConnection, string> socketDic = new Dictionary<IWebSocketConnection, string>();static void Main(){FleckLog.Level = LogLevel.Debug;var server = new WebSocketServer("ws://0.0.0.0:8181");//var socketDic = new Dictionary<IWebSocketConnection, string>();server.Start(socket =>{socket.OnOpen = () =>{Console.WriteLine("Open!");socketDic.Add(socket, null);};socket.OnClose = () =>{Console.WriteLine("Close!");socketDic.Remove(socket);};socket.OnMessage = message =>{if (message.Contains("SN:") && socketDic.ContainsKey(socket)){socketDic[socket] = message.Replace("SN:", "");}};});Client();var input = Console.ReadLine();while (input != "exit"){foreach (var socket in socketDic.ToList()){socket.Key.Send(input);}input = Console.ReadLine();}}
}

2、MQTT功能实现

MQTT服务器采用EMQX公共服务器测试,服务器域名:broker.emqx.io,端口:1883,用户名:emqx_test,密码:emqx_test

订阅主题名:123、12345

MQTT接收消息事件ApplicationMessageReceivedAsync,判断消息主题与缓存字典中的套接字是否对应,如消息主题与缓存字典SN存在包含关系,则认为此消息与网页端套接字存在关联关系,则将消息推送给此套接字。

具体实现代码:

static IMqttClient client;public static async void Client(){try{client = new MqttFactory().CreateMqttClient() as MqttClient;var build = new MqttClientOptionsBuilder().WithClientId(Guid.NewGuid().ToString().Replace("-", "").ToUpper()).WithCredentials("emqx_test", "emqx_test").WithTcpServer("broker.emqx.io", 1883).WithCleanSession(true).WithKeepAlivePeriod(TimeSpan.FromSeconds(100.5));client.ConnectedAsync += _mqttClient_ConnectedAsync;await client.ConnectAsync(build.Build());client.DisconnectedAsync += _mqttClient_DisconnectedAsync;client.ApplicationMessageReceivedAsync += _mqttClient_ApplicationMessageReceivedAsync;await client.SubscribeAsync(new MqttClientSubscribeOptions{TopicFilters = new List<MqttTopicFilter> {new MqttTopicFilter() //订阅消息对象{Topic = "123",  //订阅消息主题QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce  //消息类型},new MqttTopicFilter() //订阅消息对象{Topic = "12345",  //订阅消息主题QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce  //消息类型}}});}catch (Exception e){Console.WriteLine($"连接失败");}}private static Task _mqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg){var msg = arg.ApplicationMessage.ConvertPayloadToString();foreach (var item in socketDic){if (item.Value!=null && arg.ApplicationMessage.Topic.Contains(item.Value)){item.Key.Send($"hello {item.Value},{msg}");}}Console.WriteLine(arg.ApplicationMessage.ConvertPayloadToString());return Task.FromResult("");}private static Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg){Console.WriteLine($"客户端“{client.Options.ClientId}”已断开MQTT服务器!");return Task.FromResult("");}private static Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg){Console.WriteLine($"客户端“{client.Options.ClientId}”已连接MQTT服务器!");return Task.FromResult("");}

3、网页端实现

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head><title>websocket client</title><script type="text/javascript">var start = function () {var inc = document.getElementById('incomming');var wsImpl = window.WebSocket || window.MozWebSocket;var form = document.getElementById('sendForm');var input = document.getElementById('sendText');inc.innerHTML += "connecting to server ..<br/>";// create a new websocket and connectwindow.ws = new wsImpl('ws://localhost:8181/');// when data is comming from the server, this metod is calledws.onmessage = function (evt) {inc.innerHTML += evt.data + '<br/>';};// when the connection is established, this method is calledws.onopen = function () {inc.innerHTML += '.. connection open<br/>';ws.send("SN:12345");};// when the connection is closed, this method is calledws.onclose = function () {inc.innerHTML += '.. connection closed<br/>';}//form.addEventListener('submit', function(e){//	e.preventDefault();//	var val = input.value;//	ws.send(val);//	input.value = "";//}); }window.onload = start;</script>
</head>
<body><form id="sendForm"><input id="sendText" placeholder="Text to send" /></form><pre id="incomming"></pre>
</body>
</html>

4、测试

启动WebSocket服务器控制台应用程序;

运行MQTT.fx工具,新建连接

给12345主题发布消息,

观察网页端是否收到消息,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229300.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第7章 排序

前言 在这一章&#xff0c;我们讨论数组元素的排序问题。为简单起见&#xff0c;假设在我们的例子中数组只包含整数&#xff0c;虽然更复杂的结构显然也是可能的。对于本章的大部分内容&#xff0c;我们还假设整个排序工作能够在主存中完成&#xff0c;因此&#xff0c;元素的个…

计算机网络知识点

计算机网络中的OSI模型 OSI模型是指“国际标准化组织(SO)”提出的使各种计算机在世界范围内互通互联的网络标准框架简称开放系统互联参考模型 (OSI)。 七层模型&#xff1a;应用层、表示层、会话层、传输层、网络层&#xff08;IP协议、RARP协议、ARP协议、CIDR协议&#xff0…

【React基础二】事件绑定、组件props、条件渲染、列表、refs、组件声明周期

文章目录 1. 事件绑定2. 组件props3. 条件渲染3.1 基本概述3.2 三目运算 4. 列表5. Refs5.1 概述5.2 引用传递 Forwarding Refs 6. 组件生命周期 1. 事件绑定 React 元素的事件处理和 DOM 元素类似。但是有一点语法上的不同: React 事件绑定属性的命名采用驼峰式写法&#xf…

kafka学习笔记--Topic 数据的存储机制

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…

如何学习英语

前言 首先写一些自己的感言吧&#xff0c;其实从大学的时候就在不断地听英语&#xff0c;学英语&#xff0c;但是到毕业十几年后&#xff0c;英语一直没起到什么作用&#xff0c;当然最有作用的时候就是几次英语面试吧。 工作之后有一段学习英语的经历&#xff0c;当时花费了…

docker小白第五天

docker小白第五天 docker的私有库 有些涉密的信息代码不能放在阿里云的镜像仓库&#xff0c;因此需要构建一个个人内网专属的私有库&#xff0c;将镜像或者容器代码进行推送保存。 下载镜像docker registry 执行代码docker pull registry&#xff0c;用于搭建私服前的准备。…

Linux系统log日志简单清理

系统空间告急 清理log日志 找出当前目录中文件最大的10个文件&#xff1a; cd /var/log du -s ./* | sort -nr | head 系统日志log文件&#xff1a; ll -h /var/log/journal 只保留100MB的日志 journalctl --vacuum-size100M 系统暴力爆破SSH日志&#xff1a; ll -h /var/lo…

HTML中RGB颜色表示法和RGBA颜色表示法

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍HTML中RGB颜色表示法和RGBA颜色表示法以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题可以…

初级数据结构(六)——堆

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 初级数据结构&#xff08;五&#xff09;——树和二叉树的概念 | NULL 下一篇-> 1、堆的特性 1.1、定义 堆结构属于完全二叉树的范畴&#xff0c;除了满足完全二叉树的限制之外&#xff0c;还满…

SolidWorks二次开发 C#-读取基于Excel的BOM表信息

SolidWorks二次开发 C#-读取基于Excel的BOM表信息 问题点来源解决方案及思路相关引用链接 问题点来源 这是一位粉丝问的一个问题&#xff0c;他说到: 老师&#xff0c;请问Solidworks二次开发工程图中"基于Excel的材料明细表"怎么读取里面的数据&#xff1f; Ps:这…

leetcode刷题日志-383赎金信

思路&#xff1a;分别用两个map记录ransomNote和magazine中的字符以及出现的次数。最后遍历记录ransomNote的map&#xff0c;如果ransomNote的map中出现的magazine的map中没有出现或者出现的次数小于ransomNote的map则返回false&#xff0c;否则返回true&#xff1b; class So…

设计一个算法用于判断循环双链表是否对称。

题目描述&#xff1a;设计一个算法用于判断循环双链表是否对称。 分析&#xff1a; 分为两个情况&#xff0c;奇和偶&#xff0c;为奇&#xff08;qp&#xff09;时用q!p作为结束条件&#xff0c;为偶(p->nextq&&q->priorp)时用 q->next ! p 作为结束条件&am…

arcgis api for js 图层标注文本不显示

在打包arcgis api for js 项目后&#xff0c;更新到现场所有地图文本要素不显示的时候。 可能就是环境设置问题了&#xff0c;需要配置iis或者ngixs里边配置如下类型 iis发布的项目 1、打开iis中发布的网站 2、找到网站的MIME类型如下图 3、添加一下类型&#xff08;一个都不…

机器学习项目精选 第一期:超完整数据科学资料合集

大噶吼&#xff0c;不说废话&#xff0c;分享一波我最近看过并觉得非常硬核的资源&#xff0c;包括Python、机器学习、深度学习、大模型等等。 1、超完整数据科学资料合集 地址&#xff1a;https://github.com/krishnaik06/The-Grand-Complete-Data-Science-Materials Pytho…

安全CDN有什么作用,安全CDN工作原理是什么?

一、CDN的应用场景 CDN技术可以应用于各种类型的网站和应用程序&#xff0c;特别是对于以下几种场景&#xff0c;CDN的作用尤为明显&#xff1a; 1. 高流量网站&#xff1a;对于流量较大的网站&#xff0c;CDN可以将网站的内容分发到全球各地的节点上&#xff0c;从而分担服务…

【Linux API 揭秘】container_of函数详解

我的圈子&#xff1a; 高级工程师聚集地 我是董哥&#xff0c;高级嵌入式软件开发工程师&#xff0c;从事嵌入式Linux驱动开发和系统开发&#xff0c;曾就职于世界500强企业&#xff01; 创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01; …

1852_bash中的find应用扩展

Grey 全部学习内容汇总&#xff1a; https://github.com/GreyZhang/toolbox 1852_bash中的find应用扩展 find这个工具我用了好多年了&#xff0c;但是是不是真的会用呢&#xff1f;其实不然&#xff0c;否则也不会出现这种总结式的笔记。其实&#xff0c;注意部分小细节之后…

liunx之Samba服务器

环境&#xff1a;虚拟机CENTOS 7和 测试机相通 一、Samba服务器_光盘共享&#xff08;匿名访问&#xff09; 1.在虚拟机CENTOS 7安装smb服务&#xff0c;并在防火墙上允许samba流量通过 2. 挂载光盘 3.修改smb.conf配置文件&#xff0c;实现光盘匿名共享 4. 启动smb服务 5.在…

GB/T 19536-2015 集装箱底板用胶合板检测

集装箱底板用胶合板是指由木质单板或竹质单元与木质单板复合而成的&#xff0c;具有防虫、防腐及耐候性能&#xff0c;用于一般货物集装箱底板的胶合板。 GB/T 19536-2015集装箱底板用胶合板测试&#xff1a; 测试项目 测试方法 含水率 GB/T 17657 密度 GB/T 17657 静曲…

编写自定义函数找出二维数组(3*4)中元素的最大值与最小值,并返回其最大值与最小值,并在main函数中测试结果

编写自定义函数找出二维数组&#xff08;3*4&#xff09;中元素的最大值与最小值&#xff0c;并返回其最大值与最小值&#xff0c;并在main函数中测试结果。要求&#xff1a; 数组在main函数中使用随机函数获得赋值&#xff1b;自定义函数返回类型为void&#xff1b;输出结果在…