C# MQTT with MQTTnet lib
MQTTnet
MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). The implementation is based on the documentation from http://mqtt.org/.
- 重點是有提供client與server的機制,目前支持新版的 .NET core,這是選擇 MQTTnet 的原因
Server 端 (MQTT broker)
MQTT 服務端主要用於與多個用戶端保持連接,並處理用戶端的發佈和訂閱等邏輯。一般很少直接從服務端發送消息給用戶端(以 mqttServer.Publish(appMsg) 直接發送消息),多數情況下服務端都是轉發主題匹配的用戶端消息,在系統中起到一個中介的作用。
服務端
創建服務端是採用 MqttFactory物件的 CreateMqttServer 方法來實現,該方法需要一個MqttServerOptions() 或是 MqttServerOptionsBuilder()。
var options = new MqttServerOptions();
var mqttServer = new MqttFactory().CreateMqttServer(options);
調用其 StartAsync 方法即可啟動 MQTT 服務
await mqttServer.StartAsync(options);
在 MqttServerOptions 選項中,可以使用 ConnectionValidator 來對用戶端連接進行驗證。比如用戶端ID標識 ClientId,用戶名 Username 和密碼 Password 等。
var options = new MqttServerOptions()
{
ConnectionValidator = c =>
{
if (c.ClientId.Length < 10)
{
c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
return;
}
if (c.Username != username)
{
c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
return;
}
if (c.Password != passsword)
{
c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
return;
}
c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
}
};
服務端支援 ClientConnected、ClientDisconnected 和 ApplicationMessageReceived 事件,分別用來檢查用戶端連接、用戶端斷開以及接收用戶端發來的消息。
其中 ClientConnected 和 ClientDisconnected 事件的事件參數一個用戶端連線物件 ConnectedMqttClient,通過該物件可以獲取Client Id 和 MQTT 版本 ProtocolVersion。
ApplicationMessageReceived 的事件參數包含了 Client Id 和 MQTT 應用消息 MqttApplicationMessage 物件,通過該物件可以獲取主題 Topic、QoS QualityOfServiceLevel 和消息內容 Payload 等資訊。
Client 端
MQTT 是基於發佈/訂閱模式的,所有的用戶端均與服務端保持連接狀態。
那麼用戶端之間是如何通信的呢?
用戶端向服務端訂閱它感興趣(主題)的消息,另一些用戶端向服務端發佈(主題)消息,服務端將訂閱和發佈的主題進行匹配,並將消息轉發給匹配通過的用戶端。
用戶端
採用 MqttFactory物件的 CreateMqttClient 方法
mqttClient = new MqttFactory().CreateMqttClient()
調用其 ConnectAsync 方法即可啟動 MQTT 服務
await mqttClient.ConnectAsync(options);
調用該方法時需要傳遞一個 MqttClientOptions 物件,該選項包含了 Client Id、broker address(可以使用IP位址或功能變數名稱)Server、埠號 Port、用戶名 UserName、密碼 Password 等資訊。
改版後, 將原本物件改成了多個物件實現
MqttClientCredentials() : username, password
MqttClientTcpOptions() : server address, port
var options = new MqttClientOptions
{
ClientId = "aaa123456",
Credentials = new MqttClientCredentials
{
Username = username,
Password = passsword
},
ChannelOptions = new MqttClientTcpOptions
{
Server = brokerAddress,
Port = brokerPort,
}
};
用戶端支援 Connected、Disconnected 和 ApplicationMessageReceived 事件,用來處理用戶端與服務端連接、用戶端從服務端斷開以及用戶端收到消息的事情。
訂閱消息
用戶端連接到服務端之後,可以使用 SubscribeAsync() 非同步方法訂閱消息,該方法可以傳入TopicFilter 參數,包含主題 Topic 和 QoS。
mqttClient.SubscribeAsync(new List<TopicFilter> {
new TopicFilter("Topic name", MqttQualityOfServiceLevel.AtMostOnce)
});
發佈消息
發佈消息前需要先構建一個消息物件 MqttApplicationMessage,最直接的方法是使用其實構造函數,傳入主題、內容、QoS 等參數
var appMsg = new MqttApplicationMessage
{
Topic = "topic name",
Payload = "Message",
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
Retain = false
};
mqttClient.PublishAsync(appMsg);