MQTTnet.Server同时支持mqtt及websocket协议

Net6后写法

Net6前写法

Program.cs

复制代码
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using MQTTnet.AspNetCore;
using System;
using System.IO;

namespace MQTTnet.Server
{
    public class Program
    {
        public static int WebPort { get; set; } 

        public static void Main(string[] args)
        {
            var configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build();
            var appSettings = configuration.GetSection("AppSettings");
            WebPort = Convert.ToInt32(appSettings["WebPort"]);  
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        { 
            return Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => {
                webBuilder.UseKestrel(
                        o =>
                        {
                            o.ListenAnyIP(2883, l => l.UseMqtt());
                            o.ListenAnyIP(WebPort); // http & websocket
                        });
                webBuilder.UseStartup<Startup>();
            });
        }
    }
}

Startup.cs

复制代码
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MQTTnet.AspNetCore;
using MQTTnet.Server.Util.mqtt;
using System.Linq;

namespace MQTTnet.Server
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
             
            MQServer.UserName = "admin";
            MQServer.Password = "123456";

            services.AddHostedMqttServer(
               optionsBuilder =>
               {
                   optionsBuilder
                       .WithMaxPendingMessagesPerClient(10000)//限制每个客户端连接在 MQTT 代理上可以拥有的待处理消息数量的设置,默认值是100 
                       .WithKeepAlive();
               });

            services.AddMqttConnectionHandler();
            services.AddConnections();
            services.AddSingleton<MQServer>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MQServer mqttController)
        { 
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            } 

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            { 
                endpoints.MapControllerRoute(name: "default", pattern: "{controller=Demo}/{action=Info}/{id?}");
                //
                endpoints.MapConnectionHandler<MqttConnectionHandler>(
                   "/mqtt",
                   httpConnectionDispatcherOptions => httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector =
                       protocolList => protocolList.FirstOrDefault() ?? string.Empty);
            });

            app.UseMqttServer(
               server =>
               { 
                   server.ValidatingConnectionAsync += MQServer.ValidateConnectionAsync;
                   server.ClientConnectedAsync += MQServer.ClientConnectedAsync;
                   server.ClientDisconnectedAsync += MQServer.ClientDisconnectedAsync;
               });
        }
    }
}

MQServer.cs

复制代码
using MQTTnet.Protocol;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MQTTnet.Server.Util.mqtt
{
    public class MQServer
    { 
        public static string UserName { get; set; } = "admin";
        public static string Password { get; set; } = "123456"; 
        static readonly HashSet<string> clientIds = new();

        /// <summary>
        /// Validates the MQTT connection.
        /// </summary>
        /// <param name="args">The arguments.</param>
        public static Task ValidateConnectionAsync(ValidatingConnectionEventArgs args)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(args.UserName))
                {
                    args.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    Logger.Error($"MQServer,身份校验失败(用户名为空),ClientId:{args.ClientId}");
                    return Task.CompletedTask;
                }

                if (clientIds.TryGetValue(args.ClientId, out var _))
                {
                    args.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid;
                    Logger.Error($"MQServer,身份校验失败(有相同clientid已连接),ClientId:{args.ClientId}");
                    return Task.CompletedTask;
                }

                if (args.UserName != UserName || args.Password != Password)
                {
                    args.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    Logger.Error($"MQServer,身份校验失败(用户名或密码错误),ClientId:{args.ClientId},UserName:{args.UserName},Password:{args.Password}");
                    return Task.CompletedTask;
                } 

                args.ReasonCode = MqttConnectReasonCode.Success; 
                return Task.CompletedTask;
            }
            catch (Exception ex)
            { 
                Logger.Error("MQServer,ValidateConnectionAsync", ex);
                return Task.FromException(ex);
            }
        }

        public static async Task ClientConnectedAsync(ClientConnectedEventArgs args)
        {
            Logger.Info($"MQServer,mqtt客户端上线,id:{args.ClientId},Endpoint:{args.Endpoint},ProtocolVersion:{args.ProtocolVersion}");
            clientIds.Add(args.ClientId); 
        }

        /// <summary>
        /// Handles the client connected event.
        /// </summary>
        /// <param name="args">The arguments.</param>
        public static async Task ClientDisconnectedAsync(ClientDisconnectedEventArgs args)
        {
            Logger.Error($"MQServer,mqtt客户端离线,id:{args.ClientId},Endpoint:{args.Endpoint},DisconnectType:{args.DisconnectType},ReasonString:{args.ReasonCode}");
            clientIds.Remove(args.ClientId); 
        }
    }
}
相关推荐
岸边的风2 小时前
无需公网IP的文件交互:FileCodeBox容器化部署技术解析
网络·网络协议·tcp/ip
Zonda要好好学习3 小时前
Python入门Day4
java·网络·python
2501_915374353 小时前
UDP vs TCP:核心差异与应用场景全解析
网络协议·tcp/ip·udp
Edingbrugh.南空3 小时前
操作系统级TCP性能优化:高并发场景下的内核参数调优实践
网络协议·tcp/ip·性能优化
riverz12273 小时前
TCP backlog工作机制
服务器·网络·tcp/ip
yqcoder4 小时前
1. http 有哪些版本,你是用的哪个版本,怎么查看
网络·网络协议·http
Fanmeang7 小时前
OSPF路由过滤
运维·网络·华为·ip·路由·ospf·路由过滤
2501_915918418 小时前
接口漏洞怎么抓?Fiddler 中文版 + Postman + Wireshark 实战指南
websocket·网络协议·tcp/ip·http·网络安全·https·udp
我是阿呆同学8 小时前
仿mudou库one thread oneloop式并发服务器
网络
是阿建吖!8 小时前
【Linux | 网络】网络编程套接字
linux·网络