.Net5开发MQTT服务器

.Net5开发MQTT服务器主要借助MQTTnet包,自主开发MQTT服务器,经测试,非常稳定。

 

  

using IoT;
using JieYun.Admin.Net5;
using JieYun.IoT.Common.Models;
using JieYun.IoT.Server.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using static IoT.IoTRpc;

namespace JieYun.IoT.Server
{
    public class ServerWorker : BackgroundService
    {
        public static IMqttServer mqttServer;

        private readonly ILogger<ServerWorker> _logger;
        private readonly IoTRpcClient _client;

        public ServerWorker(ILogger<ServerWorker> logger, IoTRpcClient client, IServiceProvider provider)
        {
            _logger = logger;
            _client = client;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await StartMqttServer();
        }

        //启动Mqtt服务器
        private async Task StartMqttServer()
        {
            try
            {
                //验证客户端信息
                string hostIp = AppConfigProvider.AppConfig.IoTServerAddress;//IP地址
                int hostPort = AppConfigProvider.AppConfig.IoTServerPort;//端口号
                int timeout = 5;//超时时间
                string username = "admin";//用户名
                string password = "admin";//密码

                var optionBuilder = new MqttServerOptionsBuilder()
                  // .WithDefaultEndpointBoundIPAddress(System.Net.IPAddress.Parse(hostIp))
                   .WithDefaultEndpointPort(hostPort)
                   .WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(timeout))
                   .WithConnectionValidator(t =>
                   {
                       if (t.Username != username || t.Password != password)
                       {
                           t.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.BadUserNameOrPassword;
                       }
                       t.ReasonCode = MqttConnectReasonCode.Success;
                   });
                var options = optionBuilder.Build();

                //创建Mqtt服务器
                mqttServer = new MqttFactory().CreateMqttServer();

                //开启订阅事件
                mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(MqttNetServer_SubscribedTopic);

                //取消订阅事件
                mqttServer.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(MqttNetServer_UnSubscribedTopic);

                //客户端消息事件
                mqttServer.UseApplicationMessageReceivedHandler(MqttServe_ApplicationMessageReceivedAsync);

                //客户端连接事件
                mqttServer.UseClientConnectedHandler(MqttNetServer_ClientConnected);

                //客户端断开事件
                mqttServer.UseClientDisconnectedHandler(MqttNetServer_ClientDisConnected);

                //启动服务器
                await mqttServer.StartAsync(options);

                _logger.LogInformation("MQTT服务器已启动.");
            }
            catch (Exception e)
            {
                _logger.LogError($"MQTT服务启动失败:{e}");
            }
        }

        /// <summary>
        /// 客户订阅
        /// </summary>
        private void MqttNetServer_SubscribedTopic(MqttServerClientSubscribedTopicEventArgs e)
        {
            //客户端Id
            var ClientId = e.ClientId;
            var Topic = e.TopicFilter.Topic;
            _logger.LogInformation($"客户端【{ClientId}】订阅:{Topic}");
        }

        /// <summary>
        /// 客户取消订阅
        /// </summary>
        private void MqttNetServer_UnSubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e)
        {
            //客户端Id
            var ClientId = e.ClientId;
            var Topic = e.TopicFilter;
            _logger.LogInformation($"客户端【{ClientId}】取消订阅:{Topic}");
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        private async Task MqttServe_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs e)
        {
            _logger.LogInformation(e.ApplicationMessage.ToConsoleMessage());

            //转发消息到WebClient
            var msgStr = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
            var msg = JsonSerializer.Deserialize<MQTTMessage>(msgStr);

            if(msg.To == "SERVER"&&e.ApplicationMessage.Topic == MQTTTOPIC.UPDATE)
            {
                var msgSend = new MQTTMessage()
                {
                    From = msg.From,
                    To = "WebClient",
                    Msg = msg.Msg
                };
                await SendMessageToWebClient(msgSend);
            }
        }

        /// <summary>
        /// 客户连接
        /// </summary>
        private async Task MqttNetServer_ClientConnected(MqttServerClientConnectedEventArgs e)
        {
            var ClientId = e.ClientId;
            _logger.LogInformation($"{DateTime.Now} 客户端【{ClientId}】已连接");
           
            //通知服务器,客户端连接了
            var msg = new MQTTMessage()
            {
                From = ClientId,
                To = "SERVER",
                Msg = ClientStatus.Connected
            };
            await SendMessageToWebClient(msg);
        }

        /// <summary>
        /// 客户连接断开
        /// </summary>
        private async Task MqttNetServer_ClientDisConnected(MqttServerClientDisconnectedEventArgs e)
        {
            var ClientId = e.ClientId;
            
            _logger.LogInformation($"{DateTime.Now} 客户端【{ClientId}】已断开");

            //通知服务器,客户端断开了
            var msg = new MQTTMessage()
            {
                From = ClientId,
                To = "SERVER",
                Msg = ClientStatus.Disconnected
            };
            await SendMessageToWebClient(msg);
        }

        private async Task SendMessageToWebClient(MQTTMessage msg)
        {
            var msgStr = JsonSerializer.Serialize(msg);
            var payload = Encoding.UTF8.GetBytes(msgStr);
            MqttApplicationMessage mm = new MqttApplicationMessage()
            {
                Topic = MQTTTOPIC.UPDATE,
                Payload = payload
            };
            await mqttServer.PublishAsync(mm);
        }
    }
}
消息类MQTTMessage
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;

namespace JieYun.IoT.Common.Models
{
    public class MQTTMessage
    {
        public string Msg { get; set; }
        public string From { get; set; } = "SERVER";
        public string To { get; set; } = "e098060e71ef";

        public override string ToString()
        {
            return JsonSerializer.Serialize(this);
        }
    }
}
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace JieYun.IoT.Server
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var config = new ConfigurationBuilder()
            .AddCommandLine(args)
            .Build();


            var host = new WebHostBuilder()
              .UseConfiguration(config)
              .UseKestrel()
              .UseContentRoot(Directory.GetCurrentDirectory())
              .UseStartup<Startup>()
              .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<ServerWorker>();
                })
              .ConfigureLogging(logging => {
                  logging.ClearProviders();
                  logging.SetMinimumLevel(LogLevel.Trace);
                  logging.AddConsole();
              })
              .Build();

            host.Run();
        }
    }
}

 

posted @ 2020-12-20 18:22  接云网络  阅读(1342)  评论(1编辑  收藏  举报