dotnet / MQTTnet

MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). The implementation is based on the documentation from http://mqtt.org/.
MIT License
4.5k stars 1.07k forks source link

ASP.net Core MVC + REST server #924

Closed VallatMa closed 4 years ago

VallatMa commented 4 years ago

Describe your question

I'm trying to do a server REST and MQTT with ASP.net Core MVC for working with Unity3D. The REST server is working fine. I'm facing that issue when trying to connect to the server with WebSocket: QTTnet.Exceptions.MqttCommunicationException: Unable to connect to the remote server ---> System.Net.WebSockets.WebSocketException: Unable to connect to the remote server

I tried for one week to make it work but I'm running out of ideas. I would be grateful if you guys can tell me what did I missed.

Versions: Microsoft.AspDotNetCore.App 3.1.2 Microsoft.NETCore.App 3.1.0 Microsoft.AspNetCore.Mvc.NewtonsoftJson 3.1.3 MQTTnet 3.0.11 MQTTnet.AspNetCore 3.0.11

The client connection part:

            var id = SystemInfo.deviceUniqueIdentifier;
            var factory = new MqttFactory();
            this.mqttClient = factory.CreateMqttClient();

            // WebSocket 
            var options = new MqttClientOptionsBuilder()
                    .WithClientId(id)
                    .WithWebSocketServer("ws://127.0.0.1:5000/mqtt")
                    .WithKeepAlivePeriod(TimeSpan.FromHours(24))
                    .WithKeepAliveSendInterval(TimeSpan.FromSeconds(5))
                    .WithCleanSession()
                    .Build();

            mqttClient.UseDisconnectedHandler(async e => {
                Debug.Log("### DISCONNECTED FROM SERVER ###");
                await Task.Delay(TimeSpan.FromSeconds(5));

                try {
                    await mqttClient.ConnectAsync(options, CancellationToken.None); // Since 3.0.5 with CancellationToken
                } catch (Exception ex) {
                    Debug.Log("### RECONNECTING FAILED ###");
                    Debug.Log(ex);
                }
            });

            try {
                await mqttClient.ConnectAsync(options, CancellationToken.None); // Since 3.0.5 with CancellationToken
            } catch (Exception e) {
                Debug.Log(e);
            }

The server Programm class:

public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
            //CreateHostBuilder(args).Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder => {
            webBuilder.UseStartup<Startup>();
        });

The server Configure Service:

public void ConfigureServices(IServiceCollection services)
        {
            // requires using Microsoft.Extensions.Options
            services.Configure<DatabaseSettings>(
                Configuration.GetSection(nameof(DatabaseSettings)));

            services.AddSingleton<IDatabaseSettings>(sp =>
                sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

            // Add Services
            services.AddSingleton<Service>();

            // Add Controllers
            services.AddControllers().AddNewtonsoftJson(options => options.UseMemberCasing());

            // MQTT
            services.AddSingleton<MqttService>();
            services.AddHostedMqttServerWithServices(options => {
                var s = options.ServiceProvider.GetRequiredService<MqttService>();
                s.ConfigureMqttServerOptions(options);
            });
            services.AddMqttWebSocketServerAdapter();
            services.AddMqttConnectionHandler();
        }

The server Configure

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
            });

            // MQTT
            _ = app.UseMqttEndpoint();
            app.UseMqttServer(server => app.ApplicationServices.GetRequiredService<MqttService>().ConfigureMqttServer(server));
        }

The server MQTT service witout all the implemented interfaces

public class MqttService : IMqttServerClientConnectedHandler, IMqttServerClientDisconnectedHandler, IMqttServerApplicationMessageInterceptor, IMqttServerConnectionValidator, IMqttServerStartedHandler
    {
        IMqttServer mqtt;

        public void ConfigureMqttServerOptions(AspNetMqttServerOptionsBuilder options)
        {
            options.WithConnectionValidator(this);
            options.WithApplicationMessageInterceptor(this);
        }

        public void ConfigureMqttServer(IMqttServer mqtt)
        {
            this.mqtt = mqtt;
            mqtt.ClientConnectedHandler = this;
            mqtt.ClientDisconnectedHandler = this;
        }

Thanks in advance !

edit: changed the versions to 3.0.11

VallatMa commented 4 years ago

Here is the complete error: MQTTnet.Exceptions.MqttCommunicationException: Unable to connect to the remote server ---> System.Net.WebSockets.WebSocketException: Unable to connect to the remote server at System.Net.WebSockets.WebSocketHandle+d28.MoveNext () [0x00107] in :0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Net.WebSockets.WebSocketHandle+d24.MoveNext () [0x00383] in :0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Net.WebSockets.ClientWebSocket+d16.MoveNext () [0x000d1] in :0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 at MQTTnet.Implementations.MqttWebSocketChannel+d16.MoveNext () [0x002b7] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 at MQTTnet.Internal.MqttTaskTimeout+d0.MoveNext () [0x000c2] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 at MQTTnet.Adapter.MqttChannelAdapter+d31.MoveNext () [0x00117] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 --- End of inner exception stack trace --- at MQTTnet.Adapter.MqttChannelAdapter.WrapException (System.Exception exception) [0x00067] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 at MQTTnet.Adapter.MqttChannelAdapter+d31.MoveNext () [0x00126] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 at MQTTnet.Client.MqttClient+d36.MoveNext () [0x001d8] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at MQTTnet.Client.MqttClient+d__36.MoveNext () [0x004c4] in <0b3d8469f06c4a9d994a217bda91c9fa>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0

Yussef77 commented 4 years ago

1) Remove -> app.UseHttpsRedirection();

2) Add endpoint in Configure

 app.UseEndpoints(endpoints =>
            {
                endpoints.MapMqtt("/mqtt");  // <<------- this line
                endpoints.MapRazorPages();
                endpoints.MapControllers();
                endpoints.MapFallbackToFile("index.html");
            });
JimmyPun610 commented 4 years ago
  1. In program.cs
 webBuilder
                    .UseKestrel(o =>
                    {
                        o.ListenAnyIP(mqttPipeline, l => l.UseMqtt());
                        o.ListenAnyIP(httpPipeline);
                         //If app.UseHttpsRedirection(); is applied in startup.cs
                        o.ListenAnyIP(httpsPipeline, l => l.UseHttps());
                    })
                    .UseStartup<Startup>();
  1. In startup.cs

    app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                //Setup mqtt endpoints for websocket (localhost:{port}/mqtt}
                endpoints.MapMqtt("/mqtt");
            });
  2. Client connection

      // WebSocket 
            var options = new MqttClientOptionsBuilder()
                    .WithClientId(id)
                    //Protocol does not need to be included in parameter
                    .WithWebSocketServer("127.0.0.1:5001/mqtt")
                    //as app.UseHttpsRedirection() is applied in Server, WithTls must be apply
                    .WithTls()
                    .WithKeepAlivePeriod(TimeSpan.FromHours(24))
                    .WithKeepAliveSendInterval(TimeSpan.FromSeconds(5))
                    .WithCleanSession()
                    .Build();

More information Web socket client AspNetCore3.1 Server

SeppPenner commented 4 years ago

@JimmyPun610's solution should work, as far as I can see from the examples :)

VallatMa commented 4 years ago

Thanks for all your answers :) Because of some time pressure, I made it work by changing from WebSocket to TCP.

So here my working setup:

Startup.cs ConfigureServices

            services.AddSingleton<MqttService>();
            services.AddHostedMqttServerWithServices(options => {
                var s = options.ServiceProvider.GetRequiredService<MqttService>();
                s.ConfigureMqttServerOptions(options);
            });
            services.AddConnections();
            services.AddMqttConnectionHandler();

Startup.cs Configure

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
                endpoints.MapMqtt("/mqtt");
            });
            app.UseMqttServer(server => app.ApplicationServices.GetRequiredService<MqttService>().ConfigureMqttServer(server));

Program.cs

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder => {
            webBuilder.ConfigureKestrel(serverOptions => {
                serverOptions.ListenAnyIP(1883, l => l.UseMqtt()); 
                serverOptions.ListenAnyIP(5000, l => l.UseHttps()); 
            }).UseStartup<Startup>();
        });