Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 9 Min.

Message Queuing Telemetry Transport mit C#

Ein MQTT-Client-App-Beispiel mit Visual Studio und C#.
© dotnetpro
Message Queuing Telemetry Transport, kurz MQTT, stellt ein offenes Nachrichtenprotokoll für die Machine-to-Machine-Kommunikation (M2M) dar. MQTT wurde offiziell ab 2010 veröffentlicht und hat sich in den letzten Jahren zum De-facto-Standard für das Internet of Things (IoT) entwickelt.Hinter dem MQTT-Protokoll verbirgt sich eine leichtgewichtige Publish-Subscribe-Lösung, bei der Anwender Topics (Themen) einrichten können, über die Clients (als Publisher/Verleger) Nachrichten bereitstellen und andere Clients (als Subscriber/Abonnenten) Nachrichten entnehmen. Clients können unter MQTT beide Rollen besitzen und damit als Publisher wie auch als Subscriber fungieren. Um Art und Inhalt der Nachricht kümmert sich MQTT nicht; das bleibt der jeweiligen Implementierung und Vorgehensweise überlassen. Bild 1 zeigt die Architektur von MQTT.
Architektur von MQTT (Bild 1) © Autor
Der MQTT-Broker stellt in diesem Technologie-Stack die Vermittlereinheit dar, die den MQTT-Clients die Kommunikation ermöglicht. Insbesondere erhält ein MQTT-Broker Nachrichten, die vom Publisher veröffentlicht werden, filtert die Nachrichten nach Topics und verteilt diese an die Subscriber.

MQTT-Clients

Der Client ist der Endnutzer der Kommunikation und auch derjenige, der Nachrichten aktiv sendet. Ein Client kann zu einem Zeitpunkt sowohl Nachrichten eines Topics empfangen (Subscriber) als auch Nachrichten in dem gleichen Topic veröffentlichen (Publisher). Jeder Client identifiziert sich durch eine eindeutige Client-ID, die auch seine Session vollständig identifiziert, denn MQTT ist für die Client-Seite komplett zustandslos (stateless).Publisher senden Nachrichten auf die bereits genannten Topics (Themen). Die Topics sind hierbei hierarchisch strukturiert und ähneln von der Schreibsyntax her der Ordnerstruktur in einem Filesystem. Auch bei Topics ist der Hierachielevel jeweils mit einem Slash (/) gekennzeichnet.Topics müssen von den Clients abonniert werden, um Nachrichten zu empfangen. Schließt sich also ein neuer Client dem Nachrichtennetz an und schickt er dem MQTT-Broker eine Subscription mit dem gewünschten Topic, so wird der MQTT-Broker alle Nachrichten mit dem Topic an den Subscriber weiterleiten.Durch die Verwendung von Single-Level-Wildcards (+) und Multi-Level-Wildcards (#) können Sub­scriber mehrere Topics und deren Sub-Topics gleichzeitig abonnieren.

MQTT Quality of Service (QoS)

MQTT baut auf dem Transmission Control Protocol (TCP) als Transportprotokoll auf. Es erlaubt die Verwendung dreier unterschiedlicher Servicequalitäten (Quality of Service, QoS) mit den Angaben 0, 1 und 2:
  • Bei der niedrigsten Stufe 0 handelt es sich im Prinzip um ein Fire-and-forget-Paket. Es gibt also keine Garantie, dass die Nachricht überhaupt ankommt.
  • Bei Level 1 ist sichergestellt, dass die Nachricht mindestens einmal in der Topic Queue landet. Hier wartet der Sender auf eine Bestätigung des Empfängers (Pushback) und ist auch verpflichtet, die Nachricht erneut zu verschicken, sofern keine Empfangsbestätigung eintrifft.
  • Beim höchsten QoS-Level 2 garantiert der MQTT-Broker, dass die Nachricht genau einmal abgelegt wird. Um diese Garantie einhalten zu können, verwendet MQTT eine zweistufige Empfangsbestätigung.
Wie Sie in der Architektur (Bild 1) weiterhin erkennen können, stellt der MQTT-Broker die zentrale Komponente dar. Der MQTT-Broker verwaltet die Topics inklusive der darin enthaltenen Nachrichten sowie den Zugriff auf die Topics selbst.

Entkopplung

Somit kommuniziert der MQTT-Broker Nachrichten sowohl mit dem Publisher wie auch mit den Subscribern. Diese Art der Architektur ermöglicht eine vollständige Entkopplung der Kommunikationsteilnehmer. Es handelt sich hier also um eine 1:N-Kommunikation. Clients bleiben ständig mittels einer bestehenden TCP-Verbindung mit dem MQTT-Broker verbunden, wobei eine Nachricht im Push-Verfahren ohne Verzögerung an die registrierten Clients gesendet wird. Sowohl Subscriber als auch Publisher müssen nur im Kontext mit dem MQTT-Broker stehen und brauchen sich gegenseitig nicht zu kennen.Folglich stellt der MQTT-Broker die Vermittlungsplattform des MQTT-Nachrichtenaustauschs dar. Bei einem Ausfall des MQTT-Brokers bricht die ganze Kommunikation zusammen, da die Clients nicht mehr untereinander kommunizieren können. Hierfür gibt es die Möglichkeit, verschiedene MQTT-Broker miteinander zu verbinden, um ein redundantes System aufzubauen, sofern dies erforderlich ist.Aber neben dem reinen Austausch von Nachrichten besitzt MQTT eine Fülle von weiteren Features, die es als Kommunikationsprotokoll für das Internet of Things optimal machen, so zum Beispiel das aufgezeigte Konzept von Quality of Service. Des Weiteren unterstützt MQTT sogenannte Retained Messages, Nachrichten bei Verbindungsabbruch (Last Will and Testament, kurz LWT) und Persistent Sessions.Über das Feature Retained Messages kann ein Publisher beim Versenden einer Nachricht diese als retained (beibehalten) markieren. Der MQTT-Broker speichert diese Nachricht nun für das Topic ab, damit alle neuen Subscriber auf diesem Topic direkt diese Nachricht zugestellt bekommen.Durch die bestehende TCP-Verbindung der Clients zum MQTT-Broker wird, wie schon angesprochen, eine ereignisgetriebene Kommunikation umgesetzt. Ein Vorteil dieser Verbindung ist, dass der MQTT-Broker bei einem Verbindungsabbruch eines Clients diesen Abbruch sofort erkennen kann.Das Feature Last Will and Testament von MQTT erlaubt einem Client, eine Nachricht am MQTT-Broker zu hinterlegen, die vom Broker versendet wird, sobald die TCP-Verbindung geschlossen wurde. Des Weiteren kann ein Client beim Verbindungsaufbau entscheiden, ob er eine persistente Session anlegen möchte. Diese Session bleibt auch nach Beendigung einer TCP-Verbindung bestehen und wird bei einer erneuten Verbindung fortgeführt.

MQTT-Broker

Inzwischen gibt es eine Vielzahl von fertigen MQTT-Broker-Implementierungen. Empfehlenswert im Bereich Open­ Source sind der Message Broker (Server) von MQTTnet [1] oder auch Mosquitto aus der Eclipse Foundation [2], die beide das MQTT-Protokoll implementieren.Im kommerziellen Bereich finden Sie vor allem bei Hive­MQ [3] einen Broker beziehungsweise auch eine Cloud-Umgebung (HiveMQ Cloud), die ganz ohne lokale Installation auskommt und sofort zum Testen genutzt werden kann.Ein weiteres wichtiges Grundprinzip von MQTT ist die Einfachheit der Umsetzung am Client.

Schnell und einfach mit C# einsteigen

Nachdem Sie nun ein wenig über MQTT erfahren haben, können Sie ohne weitere Umwege in die Implementierung eines MQTT-Clients mit C# einsteigen.In diesem Artikel wird die Open-Source-MQTT-Client-Bibliothek MQTTnet verwendet, die in ein Visual-Studio-Projekt eingebettet wird. Daher sollten Sie die Entwicklungsumgebung Visual Studio in einer aktuellen Version (ab Community Edition) benutzen. Des Weiteren sind Grundkenntnisse in der C#-Programmierung mit Visual Studio von Vorteil.

Erste Schritte

Die Entwicklung einer IoT-Applikation mit C# unterscheidet sich nüchtern betrachtet nicht von einer bekannten klassischen Applikation in C#. Sie brauchen deshalb glücklicherweise das Rad nicht neu zu erfinden. Inzwischen können Sie auch bei IoT-Produkten im .NET-Umfeld auf eine Reihe von quelloffenen oder kommerziellen Frameworks zugreifen. Für das Entwickeln eines MQTT-Clients mit C# benötigen Sie nur folgende Tools:
  • einen MQTT-Broker, zum Beispiel MQTTnet Server
    (Broker), HiveMQ oder Mosquitto,
  • eine MQTT-Bibliothek oder ein MQTT-Framework,
  • Visual Studio in einer aktuellen Version.
Auf dieser Basis können Sie mit der Entwicklung eines MQTT-Clients in C# beginnen. Dieser Artikel zeigt auf, wie Sie die MQTTnet-Bibliothek verwenden, um eine Verbindung zu einem Serverless-MQTT-Broker herzustellen.Das Open-Source-Projekt MQTTnet bietet eine Implementierung bis einschließlich MQTT-5.0-Protokoll sowie TLS/SSL-Unterstützung an. Des Weiteren ist es mit fast allen unterstützten .NET-Framework-Versionen und CPU-Architekturen kompatibel. Allgemein bietet es folgende Unterstützung:
  • asynchrone Unterstützung,
  • TLS (Transport Layer Security)-Unterstützung für Clients und Server,
  • erweiterte Kommunikationskanäle wie In-Memory, TCP, TCP & TLS sowie WebSocket,
  • nur Low-Level-Implementierung von MQTT und somit keinen Overhead,
  • Performance-optimiert,
  • einheitliches API für alle unterstützten Versionen des MQTT-Protokolls.
Mehr Informationen über das MQTTnet-Projekt und eine ausführliche Dokumentation auch zum Server (Broker) finden Sie bei GitHub unter [4].

Das Visual-Studio-Projekt

Das nachfolgende Visual-Studio-Projekt soll Ihnen veranschaulichen, wie Sie einen MQTT-Client für Ihre eigenen Zwecke erstellen. Im ersten Schritt soll hier aber nur eine Nachricht an den MQTT-Broker gesendet werden und es ermöglicht werden, eine gewünschte Nachricht zu empfangen. Der Client soll also in dem Beispiel sowohl als Publisher wie auch als Subscriber fungieren.Daher ist ein GUI-Layout nicht unbedingt vonnöten. Sie können dieses aber ganz frei und individuell für Ihre Applikation entwickeln; nutzen Sie hierfür der Einfachheit halber eine Windows-Forms-, eine WPF- (.NET Framework) oder auch eine ASP.NET-Core-Web-App.Legen Sie für das Beispiel ein neues Console App-Projekt in Visual Studio an. Vergeben Sie als Project name den Begriff MQTTDemo und wählen Sie .NET 7.0 als Framework aus.Nach dem Klick auf die Schaltfläche Create erstellt Visual Studio automatisch ein lauffähiges Konsolenprogramm mit der Ausgabe Hello, World!

MQTTnet integrieren

Als Erstes können Sie für das Beispiel die beiden Codezeilen in der Klasse Program.cs entfernen. Der MQTT-Stack wird über den NuGet-Paketmanager bereitgestellt. In Ihrem Vi­sual-Studio-Projekt verwenden Sie einfach den Menüaufruf Tools | NuGet Package Manager | Manage NuGet Packages for Solution …, tragen dort in das Suchfeld MQTTnet ein und klicken auf Browse.Wählen Sie das NuGet-Paket MQTTnet in der Auswahl­liste, aktivieren Sie das Projekt auf der rechten Seite und klicken Sie auf Install(Bild 2). Ist die Installation abgeschlossen, so ist das Visual-Studio-Projekt für die Implementierung eines MQTT-Clients vorbereitet. Dank der Bibliothek MQTTnet kann der Client mit wenigen Schritten aufgebaut werden.
Auswahl des NuGet-Pakets MQTTnet (Bild 2) © Autor

MQTT-Client erstellen

Ist das NuGet-Paket installiert, fügen Sie der Klasse Program.cs die benötigte Using-Deklaration für den MQTTnet-Client hinzu. Als Nächstes wird mithilfe der Klasse MqttClientOp­tionsBuilder eine Instanz für den Zugriff auf den Broker erstellt. Hierbei werden die erforderlichen Optionen wie Broker-Adresse, Port, Benutzername und Passwort festgelegt. Um ­eine Verbindung mit dem MQTT-Broker aufzubauen beziehungsweise zu erstellen, genügt der Codeausschnitt aus Listing 1.
Listing 1: MQTT-Client erstellen
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
string broker = "myBroker.com";
int port = 8883;
string clientId = Guid.NewGuid().ToString();
string topic = "Csharp/mqtt";
string username = "myName";
string password = "myPassword";
var factory = new MqttFactory();
var mqttClient = factory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
  .WithTcpServer(broker, port)
  .WithCredentials(username, password)
  .WithClientId(clientId)
  .WithCleanSession()
  .Build(); 
Mit den Variablen werden die benötigten Werte für den Verbindungsaufbau, das Thema (Topic) und die Client-ID festgelegt. Da jeder MQTT-Client eine eindeutige Client-ID benötigt, wird über die Methode Guid.NewGuid eine neue eindeutige Kennung generiert.Über die Methode MqttFactory wird eine neue Client-­Factory erstellt und aus dieser über die Methode CreateMqttClient eine Client-Instanz angelegt.Zum Schluss werden über die Methode MqttClientOptionsBuilder die Optionen für den Client festgelegt. Möchten Sie für die Kommunikation mit dem Broker das Protokoll TSL/SSL (Transport Layer Security / Secure Sockets Layer) verwenden, so erweitern Sie einfach die Optionen mit der Methode WithTls wie folgt:

.WithTls(
  o =>
    {  
     o.SslProtocol = SslProtocols.Tls12;            
     var certificate = new X509Certificate(
       "/.../myCertificate.crt", "");
     o.Certificates = new List { 
       certificate };
    } 
Über SslProtocols.Tls12 wird der Standardwert manuell mit der angegebenen Version festgelegt. Geben Sie diesen Wert nicht an, wird er durch das Betriebssystem bestimmt. Danach werden die aktuellen Zertifikatsdateien mit ihrem Dateipfad angegeben.

Verbindung herstellen

Über den Aufruf mqttClient.ConnectAsync stellen Sie eine asynchrone Verbindung zum Broker her. Der Methodenaufruf im Code erfolgt einfach über

var connectResult = 
  await mqttClient.ConnectAsync(options); 
Die Übergabe der Verbindungsoption des MQTT-Clients erfolgt direkt in der Methode. Der asynchrone Aufruf verhindert eine Blockierung beim Veröffentlichen von Nachrichten.

Topics abonnieren

Ist die Verbindung mit dem Broker erfolgreich, können Sie über die Methode SubscribeAsync(topic) ein MQTT-Thema abonnieren, um dann die gewünschten Nachrichten zu empfangen. Listing 2 zeigt die Implementierung für das Abonnieren von Nachrichten (Topics).
Listing 2: Abonnieren von MQTT-Nachrichten
if (connectResult.ResultCode == 
    MqttClientConnectResultCode.Success)
{
  Console.WriteLine(
    "Verbindung zum Broker erfolgreich.");    
  await mqttClient.SubscribeAsync(topic);
    
  mqttClient.ApplicationMessageReceivedAsync += e =>
  {
    Console.WriteLine($"Empfangene Nachricht: " + 
      "{Encoding.UTF8.GetString(" +
      "e.ApplicationMessage.PayloadSegment)}");
    return Task.CompletedTask;
  };
} 
In der ersten Zeile im Listing 2 wird in der if-Abfrage die Verbindung zum Broker überprüft. Ist die Verbindung erfolgreich, wird das Thema abonniert und die empfangene Nachricht über die Callback-Funktion zurückgegeben.Um sich bei einem Topic wieder abzumelden, rufen Sie die Methode UnsubscribeAsync wie folgt auf:

await mqttClient.UnsubscribeAsync(topic); 

Nachrichten veröffentlichen

Um als Publisher Nachrichten an den Broker zu senden, verwenden Sie einfach die PublishAsync-Methode des MQTT-Clients. Listing 3 zeigt die simple Implementierung zum Veröffentlichen einer Nachricht. Das Senden im Beispiel erfolgt in einer Schleife, wobei alle zehn Sekunden eine Nachricht gesendet wird.
Listing 3: Umsetzung der Methode PublishAsync
for (int i = 0; i < 10; i++)
{
  var message = new MqttApplicationMessageBuilder()
    .WithTopic(topic)
    .WithPayload($"Hallo, Welt! Das ist " +
      "Nachricht Nummer: {i}")
    .WithQualityOfServiceLevel(
      MqttQualityOfServiceLevel.AtLeastOnce)
    .WithRetainFlag()
    .Build();
  await mqttClient.PublishAsync(message);
  await Task.Delay(10000); 
} 

Verbindung trennen

Wird der Client nicht mehr benötigt, sollte die Verbindung zum MQTT-Broker auch ordnungsgemäß getrennt werden. Um die Verbindung zum Client zu trennen, rufen Sie die DisconnectAsync-Methode des MQTT-Client-Objekts auf:

await mqttClient.DisconnectAsync(); 

Fazit

Über offene Bibliotheken und Frameworks im IoT-Umfeld lassen sich viele nützliche Helfer in C#-Applikationen inte­grieren. Die gezeigte Implementierung orientiert sich am Standard. Somit lässt sie sich auch ohne Weiteres auf andere Li­braries und Frameworks übertragen; Sie brauchen dazu lediglich die Methoden individuell anzusprechen beziehungsweise zu implementieren.

Neueste Beiträge

KI lässt Entwickler ihre Leidenschaft zum Programmieren neu entdecken - Motivation
Softwareentwicklung ist gleich Spaßfreie Zone? Das muss nicht sein: Der Beitrag beleuchtet, wie Teams ihren Kopf wieder freibekommen und ihre Freude am Entwickeln neu entdecken.
5 Minuten
10. Jul 2025
Spotlight #1: Azure IoT Operations, Video Teil 2/3 - DWX Spotlight
Das erste DWX Spotlight mit Special Guest Florian Bader. Im Teil 2 des Videos erklärt Florian unter anderem, wie es mit der Sicherheit bei Industrieanlagen und Messdatenerfassung aussieht.
2 Minuten
10. Jul 2025
Letzter Tag, große Themen: Git-Deep-Dive, AI-Diskussionen und fette Preise - DWX 2025
Am letzten Konferenztag wurde nicht etwa gemütlich ausgerollt – im Gegenteil. Die Agenda hatte es noch einmal in sich: ein technischer Deep-Dive, ein zukunftsweisendes Panel und ein paar ziemlich attraktive Gewinne. Hier kommt der Rückblick.
4 Minuten
4. Jul 2025
Miscellaneous

Das könnte Dich auch interessieren

Elektronische Schaltkreise im Browser simulieren - Simulation
Statt mit Steckfeld oder Lötkolben kann man auf dieser Website Schaltungen per Drag and Drop zusammenstellen und deren Verhalten testen.
2 Minuten
26. Jul 2018
Mehr Code, weniger Scrollen
Wie der BenQ RD280U und die RD-Serie die Produktivität von Entwicklern steigern (Sponsored Post)
3 Minuten
24. Jun 2025
Warum ein voller USB-Stick leichter ist als ein leerer - Wieviel wiegt eine 0
Werden USB-Laufwerke schwerer, wenn man Daten darauf speichert?
2 Minuten
30. Mär 2020
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige