Using MQTT in .NET: MQTTnet and Mosquitto Implementation
TLDR
- MQTT uses a publish/subscribe pattern, with core roles including Broker, Publisher, Subscriber, and Topic.
- Topic naming should be hierarchical (e.g.,
region/building/room/device), avoiding the use of$at the beginning (reserved for system use). - QoS level selection: QoS 0 is suitable for sensor data; QoS 1 is suitable for control commands; QoS 2 is suitable for financial transactions.
- The actual delivered QoS is the minimum of the values set by the publisher and the subscriber.
- When setting up Mosquitto using Docker, ensure
password.txthas correct permissions and set the folder owner to UID 1883. - Last Will messages are only triggered during abnormal disconnections; calling
DisconnectAsync()normally will not send them. - Retained Messages are suitable for storing the latest device status, allowing new subscribers to retrieve it immediately upon connection.
- For MQTT 5.0 persistent sessions, both
CleanStart = falseandSessionExpiryInterval(greater than 0) must be set.
MQTT Basic Concepts and Operation
MQTT is a lightweight publish/subscribe messaging protocol. The core of the system is the Broker, which is responsible for receiving messages sent by the Publisher and distributing them according to the Subscriber's subscription rules.
Topic Naming Rules and Recommendations
When do you encounter issues with chaotic topic naming: In the early stages of designing an IoT system architecture, if the topic hierarchy is not well-planned, it will be difficult to expand and maintain later.
- Hierarchical Structure: It is recommended to keep it to 3-5 levels, using lowercase English and hyphens
-. - Special Characters:
+(single-level wildcard) and#(multi-level wildcard) can only be used for subscriptions and cannot be used for publishing. - System Topics: Topics starting with
$(e.g.,$SYS/) are reserved for Broker use, and applications should avoid using them.
QoS (Quality of Service)
When do you encounter issues with message loss or duplication: In IoT scenarios with unstable network environments, you need to choose the QoS level based on the importance of the data.
- QoS 0: At most once delivery, highest performance, suitable for frequently updated sensor data.
- QoS 1: At least once delivery, ensures delivery but may result in duplicates, suitable for control commands.
- QoS 2: Exactly once delivery, uses a four-step handshake, suitable for financial or billing systems.
Setting up Mosquitto with Docker Compose
When do you encounter container startup failures or permission errors: When deploying a Mosquitto container in a Linux environment, if the mounted directory permissions are not set correctly, the container will be unable to write configuration files or data.
Key Settings and Permission Fixes
In entrypoint.sh, you must ensure that the directory owner is 1883, which is the default execution user inside the Mosquitto container:
# Fix folder permissions
chown -R 1883:1883 /mosquitto/config /mosquitto/log /mosquitto/dataTIP
For production environments, it is recommended to enable TLS encryption and refer to the official documentation to set up cafile, certfile, and keyfile.
Implementing with MQTTnet in .NET
MQTTnet is the most feature-complete MQTT library in the .NET ecosystem.
Basic Publish and Subscribe Example
The following code demonstrates how to establish a connection and exchange messages:
// Create connection options
var options = new MqttClientOptionsBuilder()
.WithTcpServer("localhost", 1883)
.WithCredentials("myuser", "mypassword")
.Build();
// Publish a message
var message = new MqttApplicationMessageBuilder()
.WithTopic("test/topic")
.WithPayload("Hello, MQTT!")
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce)
.Build();
await client.PublishAsync(message);IoT Temperature Sensor Simulation
When do you encounter difficulties in background task management: When simulating multiple sensors or performing long-term monitoring, you should use CancellationToken to gracefully stop background threads.
// Monitor system subscription
monitorClient.ApplicationMessageReceivedAsync += e => {
string json = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
// Process received data...
return Task.CompletedTask;
};Advanced Feature Implementation
Last Will and Testament
When do you encounter issues where device offline status cannot be detected: When a device goes offline abnormally due to power failure or network interruption, you can use a Last Will message to notify the monitoring system.
.WithWillTopic("status/client-001")
.WithWillPayload("offline")
.WithWillRetain(true)Persistent Session
When do you encounter issues with offline message loss: If you want the client to receive messages from the offline period after reconnecting, you must correctly configure the persistent session.
- MQTT 3.1.1: Set
CleanSession = false. - MQTT 5.0: You must set both
CleanStart = falseandSessionExpiryInterval(a number of seconds greater than 0).
WARNING
In MQTT 5.0, if SessionExpiryInterval is not set, the Broker may not retain the session even if CleanStart is set to false.
Reference Resources
- MQTT Official Website
- MQTT Version 5.0 Specification
- Eclipse Mosquitto Official Documentation
- MQTTnet GitHub Repository
Changelog
- 2025-11-15 Initial document creation.
