C#实现MQTT服务端与客户端通讯功能

关于MQTT

MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件 。

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

百度百科

MQTT示例

注: 该示例演示统一使用WPF, 简单MVVM模式演示, 复制代码需注意引用 NuGet包 GalaSoft

MQTT服务端建立:

演示界面:

演示代码:

public class MainViewModel : ViewModelBase
    {
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            ClientInsTances = new ObservableCollection<ClientInstance>();
        }

        IMqttServer mqttServer;  //MQTT服务端实例

        string message; 

        /// <summary>
        /// 消息   用于界面显示
        /// </summary>
        public string Message
        {
            get { return message; }
            set { message = value; RaisePropertyChanged(); }
        }

        ObservableCollection<ClientInstance> clientInstances; //客户端登陆缓存信息

        /// <summary>
        /// 客户端实例
        /// </summary>
        public ObservableCollection<ClientInstance> ClientInsTances
        {
            get { return clientInstances; }
            set { clientInstances = value; RaisePropertyChanged(); }
        }
     //开启MQTT服务
        public void OpenMqttServer()
        {
            mqttServer = new MqttFactory().CreateMqttServer();
            var options = new MqttServerOptions();

            //拦截登录
            options.ConnectionValidator = c =>
            {
                try
                {
                    Message += string.Format("用户尝试登录:用户ID:{0}\t用户信息:{1}\t用户密码:{2}", c.ClientId, c.Username, c.Password) + "\r\n";
                    if (string.IsNullOrWhiteSpace(c.Username))
                    {
                        Message += string.Format("用户:{0}登录失败,用户信息为空", c.ClientId) + "\r\n";

                        c.ReturnCode = MQTTnet.Protocol.MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                        return;
                    }
                    //解析用户名和密码,这个地方需要改成查找我们自己创建的用户名和密码。
                    if (c.Username == "admin" && c.Password == "123456")
                    {
                        c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
                        Message += c.ClientId + " 登录成功" + "\r\n";
                        ClientInsTances.Add(new ClientInstance()
                        {
                            ClientID = c.ClientId,
                            UserName = c.Username,
                            PassWord = c.Password
                        });
                        return;
                    }
                    else
                    {
                        c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                        Message += "用户名密码错误登陆失败" + "\r\n";
                        return;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("登录失败:" + ex.Message);
                    c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
                    return;
                }
            };
            //拦截订阅
            options.SubscriptionInterceptor = async context =>
            {
                try
                {
                    Message += "用户" + context.ClientId + "订阅" + "\r\n";
                }
                catch (Exception ex)
                {
                    Console.WriteLine("订阅失败:" + ex.Message);
                    context.AcceptSubscription = false;
                }
            };
            //拦截消息
            options.ApplicationMessageInterceptor = context =>
            {
                try
                {
                    //一般不需要处理消息拦截
                    // Console.WriteLine(Encoding.UTF8.GetString(context.ApplicationMessage.Payload));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("消息拦截:" + ex.Message);
                }
            };

            mqttServer.ClientDisconnected += ClientDisconnected;
            mqttServer.ClientConnected += MqttServer_ClientConnected;
            mqttServer.Started += MqttServer_Started;
            mqttServer.StartAsync(options);

        }

        private void MqttServer_Started(object sender, EventArgs e)
        {
            Message += "消息服务启动成功:任意键退出" + "\r\n";
        }

        private void MqttServer_ClientConnected(object sender, MqttClientConnectedEventArgs e)
        {
            //客户端链接
            Message += e.ClientId + "连接" + "\r\n";
        }

        private void ClientDisconnected(object sender, MqttClientDisconnectedEventArgs e)
        {
            //客户端断开
            Message += e.ClientId + "断开" + "\r\n";
        }

        /// <summary>
        /// 客户端推送信息    -  用于测试服务推送
        /// </summary>
        /// <param name="clientID"></param>
        /// <param name="message"></param>
        public void SendMessage(string clientID, string message)
        {
            mqttServer.PublishAsync(new MqttApplicationMessage
            {
                Topic = clientID,
                QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce,
                Retain = false,
                Payload = Encoding.UTF8.GetBytes(message),
            });
        }
    }

添加MQTT 客户端登陆实例, 用于保存客户的登陆信息,如下:

演示界面:

    /// <summary>
    /// 登陆客户端信息
    /// </summary>
    public class ClientInstance : ViewModelBase
    {
        private string clientID;
        private string userName;
        private string passWord;

        /// <summary>
        /// 识别ID
        /// </summary>
        public string ClientID
        {
            get { return clientID; }
            set { clientID = value; RaisePropertyChanged(); }
        }

        /// <summary>
        /// 账户
        /// </summary>
        public string UserName
        {
            get { return userName; }
            set { userName = value; RaisePropertyChanged(); }
        }

        /// <summary>
        /// 密码
        /// </summary>
        public string PassWord
        {
            get { return passWord; }
            set { passWord = value; RaisePropertyChanged(); }
        }

    }

MQTT客户端建立:

演示代码:

public class MainViewModel : ViewModelBase
    {
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            clientID = new Random().Next(999, 9999) + ""; //测试随机生成ClientID
        }

        IMqttClient mqttClient;  //MQTT客户端实例

        string clientID; //机器ID

        string message;

        public string Message  //用于接收当前 消息
        {
            get { return message; }
            set { message = value; RaisePropertyChanged(); }
        }
        //开启MQTT连接
        public async void SignMqttServer()
        {
            var options = new MqttClientOptionsBuilder()
             .WithClientId(clientID) //传递ClientID
             .WithTcpServer("127.0.0.1", 1883)  //MQTT服务的地址
             .WithCredentials("admin", "123456") //传递账号密码
             .WithCleanSession()
             .Build();
            mqttClient = new MqttFactory().CreateMqttClient();// .CreateManagedMqttClient();
            mqttClient.Connected += MqttClient_Connected;
            mqttClient.Disconnected += MqttClient_Disconnected;
            mqttClient.ApplicationMessageReceived += MqttClient_ApplicationMessageReceived; //创建消息接受事件

            await mqttClient.ConnectAsync(options);
            //await mqttClient.SubscribeAsync(clientID);
        }

        private void MqttClient_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
        {
            Message += "收到的信息:" + Encoding.UTF8.GetString(e.ApplicationMessage.Payload) + "\r\n";
        }

        private void MqttClient_Disconnected(object sender, MqttClientDisconnectedEventArgs e)
        {
            Message += "客户端断开";
        }

        private void MqttClient_Connected(object sender, MqttClientConnectedEventArgs e)
        {
            Message += "客户端已连接" + "\r\n";
            mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic(clientID).Build()); //关联服务端订阅, 用于接受服务端推送信息

        }
    }

演示界面:

实际演示效果(GIF)

到此这篇关于C#实现MQTT服务端与客户端通讯功能的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用Docker搭建MQTT服务器的过程详解

    1. 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/synbop/emqttd:2.3.6 2. 运行镜像 –name 名字 -p 18083 服务器启动端口 -p 1882 TCP端口 -p 8083 WS端口 -p 8084 WSS端口 -p 8883 SSL端口 -d 指定容器 docker run --name emq -p 18083:18083 -p 1883:1883 -p 8084:8084 -p 8883:8883 -p

  • vue中利用mqtt服务端实现即时通讯的步骤记录

    MQTT协议 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和制动器(比如通过Twitter让房屋联网)的通信协议. MQTT是轻量级基于代理的发布/订阅的消息传输协议,它可以通过很少的代码和带宽和远程设备连接.例如通过卫星和代理连接,通过拨号和医疗保健提供者连接,以及在一些自动化或小型设备上,而且由于小巧

  • 教你在windows下搭建MQTT服务器的方法

    目录 一.下载mosquitto 二.配置mosquitto 1. 安装路径打开命令行界面 2. 设置user及password 3. 配置文件检查 4. 设置端口 5. 订阅者 6. 发布者 7. 命令行测试 三.MQTTX 1. 连接服务器 2. 订阅topic 3. 发布消息 一.下载mosquitto 点击下载安装程序 下载地址 二.配置mosquitto 1. 安装路径打开命令行界面 2. 设置user及password 执行:mosquitto_passwd.exe -c pwfil

  • 如何在uniapp项目中使用mqtt

    由于要取一些实时数据并在手机app上展示,就想到用mqtt进行即时通讯. 下面附上uniapp中引入mqtt的全过程: 一.uniapp插件市场的参考插件 https://ext.dcloud.net.cn/plugin?id=854 二.具体引入过程 1.安装mqtt和uuid 在uniapp项目根目录下分别运行安装mqtt和uuid的命令行,因为后面会用uuid生成mqtt的clientId,所以这边就一起安装了. npm install mqtt@3.0.0 npm install uui

  • C# Mqtt 断线重连的实现代码

    在通过 MqttClient 客户端连接之后,在服务端服务重启时,客户端如果没有重连机制,则无法再接收到订阅的消息. 使用的 Mqtt 组件为:M2Mqtt.Net.dll 一些特性发现 (1)如果提供的服务端地址是不可解析的,会引发异常无法实例化 MqttClient 对象. (2)Connect 无法连接时会引发异常,IsConnected 为 false. (3)服务端断开会触发客户端的 ConnectionClosed 事件,IsConnected 为 false. (4)重新 Conn

  • 微信小程序+mqtt,esp8266温湿度读取的实现方法

    第一.原理讲解 esp8266 通过mqtt发布消息,微信小程序通过mqtt 订阅消息,小程序订阅后,就可以实时收到esp8266 传输来的消息. 第二.温湿度测试 这里使用的是D4口. 本demo 是利用arduino IDE开发,关于arduino IDE 的ESP8266环境配置可参考:环境配置: 点击跳转 安装库 本案例使用一个非常简单易用且与ESP8266配合使用的是Simple DHT传感器库.可以通过Arduino IDE Library Manager轻松安装该库. 在 ardu

  • SpringBoot整合MQTT并实现异步线程调用的问题

    目录 为什么选择MQTT 使用背景 代码实现 基础代码 异步线程处理实现 为什么选择MQTT MQTT的定义相信很多人都能讲的头头是道,本文章也不讨论什么高大上的东西,旨在用最简单直观的方式让每一位刚接触的同行们可以最快的应用起来 先从使用MQTT需要什么开始分析: 消息服务器 不同应用/设备之间的频繁交互 可能涉及一对多的消息传递 基于SpringBoot通过注解实现对mqtt消息处理的异步调用 使用背景 生产环境下, 由于mqtt 生产者生产的消息逐渐增多, 可能会导致消息堆积. 因此需要消

  • go语言实现mqtt协议的实践

    目录 一.什么是MQTT 二.Go语言MQTT服务器Broker的搭建 三.Go客户端访问简单API 一.什么是MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布. MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务.作为一种低开销.低带宽占用的

  • C#实现MQTT服务端与客户端通讯功能

    关于MQTT MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议.它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件 . MQTT是一个基于客户端-服务器的消息发布/订阅传输协议.MQTT协议是轻量.简单.开放和易于实现的,这些特点使它适用范围非常广泛.在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT).其在,通过卫星链路

  • PHP编程实现的TCP服务端和客户端功能示例

    本文实例讲述了PHP编程实现的TCP服务端和客户端功能.分享给大家供大家参考,具体如下: 1.修改php.ini,打开extension=php_sockets.dll 2.服务端程序SocketServer.php <?php //确保在连接客户端时不会超时 set_time_limit(0); //设置IP和端口号 $address = "127.0.0.1"; $port = 3046; /** * 创建一个SOCKET * AF_INET=是ipv4 如果用ipv6,则参

  • Java利用TCP实现服务端向客户端消息群发的示例代码

    目录 前言 代码 tcp服务端代码 ServerThread 线程类 TcpTool 消息群发工具类 Tcp客户端代码 前言 项目需要和第三方厂商的服务需要用TCP协议通讯,考虑到彼此双方可能都会有断网重连.宕机重启的情况,需要保证 发生上述情况后,服务之间能够自动实现重新通信.研究测试之后整理如下代码实现.因为发现客户端重启后,对于服务端来说原来的客户端和服务端进程进程已经关闭,启动又和服务端新开了一个进程.所以实现原理就可以通过服务端向客户端群发实现,断开重新连接通讯. 代码 tcp服务端代

  • WIN7下ORACLE10g服务端和客户端的安装图文教程

    win7下安装oracle10g服务端和客户端方法如下所示: 如何卸载Oracle 10g 软件环境: 1.Windows XP + Oracle 10g 2.Oracle安装路径为:d:\Oracle 实现方法: 1.开始->设置->控制面板->管理工具->服务停止所有Oracle服务; 2.开始->程序->Oracle – OraDb10g_home1>Oracle Installation Products-> Universal Installer

  • 使用socket进行服务端与客户端传文件的方法

    逻辑: 1.客户端将需要查找的文件名以流的形式传给服务端 2.服务端接受客户端的连接,把流转化为字符串,进行一个目录的遍历,查找是否存在需要的文件,若未找到,则输出未找到,若找到,则将文件转化为流,传给客户端 3.客户端准备接受,将服务端传过来的流转化为文件,存储下载. 4,至此,完成一个简单的客户端与服务端传输文件的小栗子~ Client.Java package com.ysk; import java.io.BufferedReader; import java.io.FileOutput

  • ASP.NET简单获取服务端和客户端计算机名称的方法

    本文实例讲述了ASP.NET简单获取服务端和客户端计算机名称的方法.分享给大家供大家参考,具体如下: //获取服务端计算机名称 string serverPCName = System.Net.Dns.GetHostName(); //获取客户端计算机名称 System.Net.IPAddress clientIP = System.Net.IPAddress.Parse(Request.UserHostAddress);//根据目标IP地址获取IP对象 System.Net.IPHostEnt

  • nodejs socket实现的服务端和客户端功能示例

    本文实例讲述了nodejs socket实现的服务端和客户端功能.分享给大家供大家参考,具体如下: 使用node.js的net模块能很快的开发出基于TCP的服务端和客户端.直接贴代码. server.js /** * Created with JetBrains WebStorm. * User: Administrator * Date: 12-10-26 * Time: 下午3:44 * To change this template use File | Settings | File T

  • nodejs socket服务端和客户端简单通信功能

    本文实例讲述了通过node.js的net模块实现nodejs socket服务端和客户端简单通信功能,可以用作客户端对服务端的端口监听以及事件回执. server端代码 var net = require('net'); //模块引入 var listenPort = 8080;//监听端口 var server = net.createServer(function(socket){ // 创建socket服务端 console.log('connect: ' + socket.remoteA

  • golang实现简单的udp协议服务端与客户端示例

    本文实例讲述了golang实现简单的udp协议服务端与客户端.分享给大家供大家参考,具体如下: 其实udp没有什么服务端和客户端的概念了,只是一个发一个收而已,只是这样较方便能识别和理解. 服务端: 复制代码 代码如下: package main import (     "fmt"     "net" ) func main() {     // 创建监听     socket, err := net.ListenUDP("udp4", &am

随机推荐