MQTTnet icon indicating copy to clipboard operation
MQTTnet copied to clipboard

Unable to connect over websockets

Open lukedukeus opened this issue 1 year ago • 6 comments

Describe the bug

I am able to connect over TCP on port 1833 or 5000, but not over websockets on any port

Which component is your bug related to?

  • Server

To Reproduce

Steps to reproduce the behavior:

  1. Download the attached demo, and start it.
  2. Using MQTT Explorer, attempt to connect over WS

Expected behavior

It should be able to connect

Screenshots

Animation4

Additional context / logging

The server does not produce any logs as to why connecting failed

MQTTtest.zip

lukedukeus avatar Dec 08 '23 16:12 lukedukeus

It seems that you selected a TCP connection. So the part "/mqtt" is wrong at the host test box.

Also please share the code in the ticket. We will not download any zip file and execute it's content 😉

chkr1011 avatar Dec 09 '23 17:12 chkr1011

Here's a repo with the demo code: https://github.com/lukedukeus/mqtt-broker-test

I tried with / without the "/mqtt" part, and it didn't seem to make a difference. Please let me know if anything looks off in the code.

Thanks!

lukedukeus avatar Dec 09 '23 21:12 lukedukeus

Same problem here... ws://localhost:5000/mqtt not working, ERR_UNKNOWN_URL_SCHEME (not working using MQTT Explorer) But if you use https://github.com/mqttjs/MQTT.js and put http://localhost:5000/mqtt it works.

joaodotneto avatar Dec 20 '23 14:12 joaodotneto

Maybe the same problem

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Server;

namespace Client.Client
{
    public class ClientService
    {
        private readonly IMqttClient _mqttClient;
        private readonly MqttClientOptions _options;

        public ClientService()
        {
            _options = new MqttClientOptionsBuilder()
                .WithWebSocketServer(o => o.WithUri("localhost:8000/mqtt"))
                .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
                .WithClientId(Guid.NewGuid().ToString())
                .Build();
            _mqttClient = new MqttFactory().CreateMqttClient();
        }

        public async Task Connect()
        {
            await _mqttClient.ConnectAsync(_options, CancellationToken.None);
        }

        public async Task Subscripe()
        {
            await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("my/topic").Build());
        }

        public async Task Publish()
        {
            var message = new MqttApplicationMessageBuilder()
                .WithTopic("/MQTTnet/is/awesome")
                .Build();

            await _mqttClient.PublishAsync(message, CancellationToken.None);
        }
    }
}

Can not connect to server by using the client.

But with the MQTT Explorer, there is no problem. image

Metaln00b avatar Apr 15 '24 14:04 Metaln00b

@Metaln00b I guess, you need to tell the server to speak Mqtt version 5.0 as well if you tell the client to connect with it...

SeppPenner avatar Apr 15 '24 17:04 SeppPenner

@Metaln00b I guess, you need to tell the server to speak Mqtt version 5.0 as well if you tell the client to connect with it...

Thank you for the fast response.

public ClientService()
{
    _options = new MqttClientOptionsBuilder()
        .WithTcpServer("127.0.0.1") /* Changed */
        .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500) /* no matter */
        .WithClientId(Guid.NewGuid().ToString())
        .Build();
    _mqttClient = new MqttFactory().CreateMqttClient();
}

I have not found a quick way to assign the protocol to the server. However, it makes no difference whether I specify this in the client or not. I have found that it works with TCP. I use the server example for ASP.Net 5.0 but in 8.0.

using MQTTnet.AspNetCore;
using Server.Controller;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(kestrel =>
{
    kestrel.ListenAnyIP(1883, l => l.UseMqtt());

    // This will allow MQTT connections based on HTTP WebSockets with URI "localhost:5000/mqtt"
    // See code below for URI configuration.
    kestrel.ListenAnyIP(8000); // Default HTTP pipeline
});

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddHostedMqttServer(
    optionsBuilder =>
    {
        optionsBuilder.WithDefaultEndpoint();
    });

builder.Services.AddMqttConnectionHandler();
builder.Services.AddConnections();

builder.Services.AddSingleton<MqttController>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseEndpoints(
    endpoints =>
    {
        _ = endpoints.MapConnectionHandler<MqttConnectionHandler>(
            "/mqtt",
            httpConnectionDispatcherOptions => httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector =
                protocolList => protocolList.FirstOrDefault() ?? string.Empty);
    });

app.UseMqttServer(
    server =>
    {
        server.ValidatingConnectionAsync += app.Services.GetRequiredService<MqttController>().ValidateConnection;
        server.ClientConnectedAsync += app.Services.GetRequiredService<MqttController>().OnClientConnected;
    });

app.MapRazorPages();

app.Run();

Many thanks

Metaln00b avatar Apr 16 '24 14:04 Metaln00b