Getting Started
In the world of IoT and real-time communication, MQTT (Message Queuing Telemetry Transport) has become one of the most popular lightweight messaging protocols. It is designed for scenarios where network bandwidth and device resources are limited, making it perfect for sensors, controllers, and connected applications. If you want to know more about MQTT vs AMQP refer to our earlier blog post MQTT vs AMQP: Key Differences, Use Cases, and Tools
In this blog, we’ll walk through a hands-on introduction to MQTT using the Mosquitto broker. We’ll learn how to:
- Use Mosquitto clients (mosquitto_pub and mosquitto_sub) to publish and subscribe to MQTT topics.
- Build a Python client for subscribing and processing messages.
- Use QoS level
- Set up secure communication using TLS to ensure data privacy and authentication.
By the end of this tutorial, we’ll have a complete
understanding of how MQTT works in practice, from publishing messages to
subscribing clients, all running over a secure, lightweight messaging
infrastructure.
Setting
Up the Mosquitto MQTT Broker
Before we start publishing and subscribing to messages,
let’s set up our MQTT broker. We’ll use Eclipse Mosquitto, one of the most
popular open source MQTT brokers, known for its simplicity and reliability.
If you want to know more about software licensing type then
go for our previous blog post Software
Licenses: Open Source vs Proprietary
Install Mosquitto (Windows OS)
Download the Mosquitto installer from the official Mosquitto website https://mosquitto.org/download/
Run the installer and select the options to install both broker and client tools.
Once the broker is up, test its default port (1883 for
non-TLS):
netstat -an | findstr 1883
If mosquito is running following result should come in response
Test Basic Publish/Subscribe
Open two terminals, in terminal 1 subscribe to a topic and
in terminal 2 publish to a topic.
Terminal 1 – Subscribe to a topic:
mosquitto_sub -h localhost -t test/topic
Terminal 2 – Publish a message:
mosquitto_pub -h localhost -t test/topic -m "Hello
MQTT!"
As soon as the message will publish in Terminal 2, the same
will appear in terminal 1
Creating
a .NET MQTT Client to Subscribe and Receive Messages
Once the Mosquitto broker is live, we can connect to it
programmatically using an MQTT client library. In .NET, the most popular and
reliable choice is MQTTnet, an open-source library that fully supports MQTT
v3.1.1 and v5.
Let’s walk through the process of building a simple
subscriber in C#.
1. Create a New .NET Console Application
Open visual studio and create a new .NET Console Application
“MQTT.NETSubscriber”
2. Install the MQTTnet Package
Right click on solution project and click on Manage Nuget
Package to open it. Browse for MQTTnet library and install the latest stable
version.
Note: - In the code example I have used MQTTNet v3.1.2 for
.NET framework 4.7.2
If you are using .NET Core feel free to use the higher compatible version
3. Write the MQTT Subscriber Code
I have created a separate class file having methods to create
MQTT instances, connect to MQTT broker and subscribe for events from topic. In
the main method I am calling for subscription.
The full project can be found in the GITHub repo.
Program.cs code
using System.Threading.Tasks;
using System.Configuration;
namespace MQTT.NETSubscriber
{
public class Program
{
static async Task Main(string[] args)
{
string broker = ConfigurationManager.AppSettings["Broker"];
int port = Convert.ToInt32(ConfigurationManager.AppSettings["Port"]);
string testTopic = ConfigurationManager.AppSettings["Topic"];
MQTTSubscriber mQTTSubscriber = new MQTTSubscriber(broker, port);
await mQTTSubscriber.ConnectAsync();
await mQTTSubscriber.SubscribeAsync(testTopic);
Console.WriteLine("Waiting for messages. Press any key to exit...");
Console.ReadKey();
await mQTTSubscriber.DisconnectAsync();
}
}
}
MQTTSubscriber.cs code
public class MQTTSubscriber
{
private
MqttFactory _factory;
private
IMqttClient _client;
private
IMqttClientOptions _clientOptions;
public MQTTSubscriber(string
broker,int? port)
{
// Create a
new MQTT client
_factory = new
MqttFactory();
_client=
_factory.CreateMqttClient();
// Configure
client options
_clientOptions
= new MqttClientOptionsBuilder()
.WithTcpServer(broker, port)
.WithClientId("DotNetSubscriber")
.Build();
// Attach
message handler (old syntax for v3.x)
_client.ApplicationMessageReceivedHandler =
new
MqttApplicationMessageReceivedHandlerDelegate(OnMessageReceived);
}
public async Task
ConnectAsync()
{
Console.WriteLine("Subscriber is connecting to MQTT broker...");
await
_client.ConnectAsync(_clientOptions);
Console.WriteLine("Subscriber connected successfully!");
}
public async Task
SubscribeAsync(string topic)
{
if
(!_client.IsConnected)
{
Console.WriteLine("Client not connected. Connecting now...");
await
ConnectAsync();
}
await
_client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
Console.WriteLine($"Subscriber subscribed to topic: {topic}");
}
public async Task
DisconnectAsync()
{
await
_client.DisconnectAsync();
Console.WriteLine("Disconnected from MQTT broker.");
}
#region private
methods
// Message handler
(for v3.x)
private void
OnMessageReceived(MqttApplicationMessageReceivedEventArgs e)
{
string topic =
e.ApplicationMessage.Topic;
string message
= Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? Array.Empty<byte>());
Console.WriteLine($"Message received on topic '{topic}': {message}");
}
#endregion
}
Check the result
Run the .NET program
Open a command prompt and use Mosquitto_pub command to
publish a message to topic TestTopic1 like below :
>mosquitto_pub -h localhost -t TestTopic1 -m
"Hello MQTT!!!!!!!"
You can find the message is printing in .NET program console
window.
Creating
a .NET MQTT Client to Publish Messages
We’ll use the same MQTTnet v3.1.2 library, but this time focus on sending messages to a topic that our subscriber can receive.
public class MQTTPublisher
{
private readonly
MqttFactory _factory;
private readonly
IMqttClient _client;
private readonly
IMqttClientOptions _clientOptions;
public MQTTPublisher(string
broker, int? port)
{
// Create MQTT
client
_factory = new
MqttFactory();
_client =
_factory.CreateMqttClient();
// Configure
client options
_clientOptions
= new MqttClientOptionsBuilder()
.WithTcpServer(broker, port)
.WithClientId("DotNetPublisher")
.Build();
}
// Connect to
broker
public async Task
ConnectAsync()
{
Console.WriteLine("Publisher is connecting to MQTT broker...");
await
_client.ConnectAsync(_clientOptions);
Console.WriteLine("Publisher connected successfully!");
}
// Publish message
to topic
public async Task
PublishAsync(string topic, string message)
{
if
(!_client.IsConnected)
{
Console.WriteLine("Client not connected. Connecting now...");
await
ConnectAsync();
}
var
mqttMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(Encoding.UTF8.GetBytes(message))
.WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce)
.WithRetainFlag(false)
.Build();
await
_client.PublishAsync(mqttMessage);
Console.WriteLine($"Message published to '{topic}': {message}");
}
// Disconnect from
broker
public async Task
DisconnectAsync()
{
await
_client.DisconnectAsync();
Console.WriteLine("Disconnected from MQTT broker.");
}
}Change the program.cs file to invoke publisher methods . So
once the program will run both publisher and subscriber should connect to MQTT
broker where publisher will be ready to publish and subscriber will be
listening the topic.
static async Task Main(string[] args)
{
string broker = ConfigurationManager.AppSettings["Broker"];
int port = Convert.ToInt32(ConfigurationManager.AppSettings["Port"]);
string topic = ConfigurationManager.AppSettings["Topic"];
// Create both subscriber and publisher instances
var subscriber = new MQTTSubscriber(broker, port);
var publisher = new MQTTPublisher(broker, port);
// Connect both
await subscriber.ConnectAsync();
await subscriber.SubscribeAsync(topic);
await publisher.ConnectAsync();
Console.WriteLine("Publisher connected. Type messages to publish (type 'exit' to quit).");
// Publish messages and see them received by the subscriber
while (true)
{
Console.Write("Message: ");
string message = Console.ReadLine();
if (string.Equals(message, "exit", StringComparison.OrdinalIgnoreCase))
break;
await publisher.PublishAsync(topic, message);
}
// Disconnect both
await publisher.DisconnectAsync();
await subscriber.DisconnectAsync();
Console.WriteLine("Disconnected both clients. Press any key to exit...");
Console.ReadKey();
}
Now we can see the result that once we publish any message, the
same message is available to subscriber.
Understanding
and Implementing MQTT QoS Levels in .NET
let’s dive into the next topic in our list QoS (Quality
of Service) Levels. This is one of the most important MQTT concepts for
reliable message delivery.
MQTT defines three Quality of Service (QoS) levels that determine how reliably messages are delivered between the publisher and subscriber.
|
QoS |
Level Name |
Guarantee |
Description |
|
0 |
At most once |
No
acknowledgement |
Message is
delivered once, if possible, but can be lost. Fastest but least reliable. |
|
1 |
At least once |
Guaranteed
delivery, may be duplicate |
Broker stores
message until it gets an acknowledgment (PUBACK). Subscriber may get
duplicates. |
|
2 |
Exactly once |
Guaranteed delivery,
exactly once |
Safest but
slowest — ensures message is received only once using a 4-step handshake. |
1aWe can configure QoS in both publisher and subscriber.
Set QoS in Subscriber.cs
public async Task SubscribeAsync(string topic, int qosLevel
= 1)
{
if
(!_client.IsConnected)
{
Console.WriteLine("Client not connected. Connecting now...");
await
ConnectAsync();
}
var qos =
(MQTTnet.Protocol.MqttQualityOfServiceLevel)qosLevel;
await
_client.SubscribeAsync(new MqttTopicFilterBuilder()
.WithTopic(topic)
.WithQualityOfServiceLevel(qos)
.Build()
);
Console.WriteLine($"Subscriber
subscribed to topic: {topic} with QoS {qosLevel}");
}
In previous publisher code we are already used QoS 1
Setting
Up Secure MQTT Communication Using TLS
As MQTT is often used in IoT systems and enterprise
integrations, securing communication between clients and brokers is essential.
Without encryption, sensitive information can be intercepted or tampered with
during transmission. To protect your data, MQTT supports Transport Layer
Security (TLS) ensuring that messages are securely transmitted and both client
and broker can authenticate each other.
1.
Get the CA certificate
The very first step is to get the certificate from trusted
certificate authority. It’s like a notary office that says: “I verify
that this organization’s identity is legitimate.” It owns a private key
(ca.key) and public certificate (ca.crt).
2.
Create the Broker Certificate (Server
Certificate)
Our MQTT broker (Mosquitto) needs it’s own certificate like
identity card. This certificate (server.cert) contains it’s public key and identity
info (like CN=Localhost). But the world won’t trust this certificate unless
signed by a CA.we have to sign the broker certificate using CA private key.
Step1
So, first we have to create the private key of the broker
(server.key) using openssl .
Step2
Then create a certificate signing request (CSR).
CRS contains
1.public key derived from private key
2.The broker’s identity details like CN,organization, etc
Step3
Sign the broker CSR with CA certificate and key to generate
server certificate
3.
How MQTT Client(publisher/subscriber)
authenticate MQTT broker
When client connects to broker, the broker
presents it’s certificate(server.cert). The client then check who signed it by
seeing the CA info inside it.The client is already having the CA’s public
certificate (CA.cert) to verify the signature.
If the verification succeeds then broker is
authentic else no.
Setting
Up Secure MQTT Communication Using TLS
As MQTT is often used in IoT systems and enterprise
environments, securing communication between clients and brokers is essential.
Without encryption, sensitive data can be intercepted or tampered with during
transmission. To ensure confidentiality and authenticity, MQTT supports Transport
Layer Security (TLS) which encrypts
messages and allows both client and broker to verify each other’s identity.
1.Get the CA Certificate
The first step is to get a certificate from a trusted Certificate
Authority (CA).
Think of the CA like a digital notary office that says: “I verify that this
organization’s identity is legitimate.”
The CA owns:
- a private
key (ca.key) – used to sign other certificates
- a public
certificate (ca.crt) – used by clients to verify signatures
If you’re testing locally, you can create your own
self-signed CA using OpenSSL.
2.Create the Broker Certificate (Server Certificate)
Your MQTT broker (Mosquitto) needs its own digital identity
card — the server certificate (server.crt).
This file contains the broker’s public key and identity details (like CN=localhost).
However, the world (clients) won’t trust this certificate unless
it’s signed by the CA.
That’s why we must use the CA’s private key to sign the broker’s certificate.
Step 1: Create the broker’s private key
openssl genrsa -out
server.key 2048
Step 2: Create a Certificate Signing Request (CSR)
openssl req -new -key
server.key -out server.csr
The CSR includes:
- The
broker’s public key
- Identity
details such as CN (Common Name), Organization, etc.
Step 3: Sign the CSR using the CA’s certificate and
key
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key
-CAcreateserial \
-out server.crt -days 365 -sha256
This produces the server certificate (server.crt)
signed by the CA.
3.How MQTT Clients Authenticate the Broker
When a client (publisher/subscriber) connects to the broker:
- The broker
presents its certificate (server.crt).
- The client
checks who signed it by reading the CA information inside the certificate.
- The client
uses its trusted CA certificate (ca.crt) to verify the broker’s
certificate signature.
If the verification succeeds, the client trusts the broker
and establishes a secure TLS connection.
If not, the connection is rejected ensuring that the client never talks to an
untrusted server.
Generated documents summary Table
|
File Name |
Description |
Purpose |
Used By |
|
CA.key |
Private key
of the CA |
Used to sign
and issue other certificate |
CA |
|
CA.cert |
Public
certificate of the CA |
Shared with
clients so they can verify certificates signed by CA |
Client |
|
Server.key |
Private key
of the MQTT Broker |
Used to encrypt
and authenticate messages from the broker |
Broker |
|
Server.csr |
Certificate
signing request |
Contains
broker’s public key and identity details sent to CA for signing |
Temporary
during creation |
|
Server.cert |
Signed
certificate from MQTT Broker |
Proves the
broker’s identity to client. Used in TLS handshake |
Broker |
To be continued for..
4.Configuring Mosquitto for TLS Communication
5. Configuring .NET MQTT Client for Secure TLS Connection

No comments:
Post a Comment