CloudAMQP with MQTT and .NET
We recommend MQTTnet, the .NET Foundation’s
MQTT client. The examples are .NET 10
file-based apps:
dotnet run installs the MQTTnet package their #:package line names. In a
project, add it with:
dotnet add package MQTTnet
Publish and subscribe
Set MQTT_HOST, MQTT_PORT, MQTT_USERNAME and MQTT_PASSWORD to the MQTT
details on your instance’s details page in the CloudAMQP console. Port 8883
uses TLS. Without them, the examples connect to a local broker.
Save the publisher as publisher.cs:
#:package MQTTnet@5.2.0.1603
using MQTTnet;
using MQTTnet.Formatter;
using MQTTnet.Protocol;
var port = int.Parse(Environment.GetEnvironmentVariable("MQTT_PORT") ?? "1883");
var options = new MqttClientOptionsBuilder()
.WithTcpServer(Environment.GetEnvironmentVariable("MQTT_HOST") ?? "localhost", port)
.WithCredentials(Environment.GetEnvironmentVariable("MQTT_USERNAME") ?? "guest", Environment.GetEnvironmentVariable("MQTT_PASSWORD") ?? "guest")
.WithTlsOptions(tls => tls.UseTls(port == 8883))
// MQTTnet defaults to MQTT 5, LavinMQ supports MQTT 3.1.1
.WithProtocolVersion(MqttProtocolVersion.V311)
.Build();
using var client = new MqttClientFactory().CreateMqttClient();
await client.ConnectAsync(options);
// QoS 1 completes once the broker has sent its PUBACK
await client.PublishStringAsync("hello", "Hello world!", MqttQualityOfServiceLevel.AtLeastOnce);
Console.WriteLine(" [x] Sent 'Hello world!'");
await client.DisconnectAsync();
Save the subscriber as worker.cs:
#:package MQTTnet@5.2.0.1603
using MQTTnet;
using MQTTnet.Formatter;
using MQTTnet.Protocol;
var port = int.Parse(Environment.GetEnvironmentVariable("MQTT_PORT") ?? "1883");
var options = new MqttClientOptionsBuilder()
.WithTcpServer(Environment.GetEnvironmentVariable("MQTT_HOST") ?? "localhost", port)
.WithCredentials(Environment.GetEnvironmentVariable("MQTT_USERNAME") ?? "guest", Environment.GetEnvironmentVariable("MQTT_PASSWORD") ?? "guest")
.WithTlsOptions(tls => tls.UseTls(port == 8883))
// MQTTnet defaults to MQTT 5, LavinMQ supports MQTT 3.1.1
.WithProtocolVersion(MqttProtocolVersion.V311)
.Build();
using var client = new MqttClientFactory().CreateMqttClient();
await client.ConnectAsync(options);
// Each message is acked when the handler's task completes
client.ApplicationMessageReceivedAsync += e =>
{
Console.WriteLine($" [x] Received '{e.ApplicationMessage.ConvertPayloadToString()}'");
return Task.CompletedTask;
};
await client.SubscribeAsync("hello", MqttQualityOfServiceLevel.AtLeastOnce);
Console.WriteLine(" [*] Waiting for messages. To exit press CTRL+C");
await Task.Delay(Timeout.Infinite);
Run dotnet run worker.cs in one terminal and dotnet run publisher.cs in
another.
A runnable example is in dotnet/mqttnet in cloudamqp/examples.
Good to know
- Put the vhost in the username, as
vhost:user. MQTT has no vhost of its own, and the console shows the username that way. - Connect with MQTT 3.1.1. MQTTnet 5 defaults to MQTT 5, which LavinMQ
doesn’t support, so set
WithProtocolVersion(MqttProtocolVersion.V311). UseTls()verifies the server certificate.- Use QoS 1, so
PublishStringAsynccompletes once the broker has sent its PUBACK, and each message is acked when the handler’s task completes. - MQTTnet 5 doesn’t reconnect. Handle
DisconnectedAsync, connect again and subscribe again.