1. 程式人生 > 其它 >基於MqttNet的二次封裝MQTT在.Net中的使用例項,附呼叫

基於MqttNet的二次封裝MQTT在.Net中的使用例項,附呼叫

最近需要處理一些協議連線和呼叫。

一開始想著是基於RabbitMq(我們本身就在用)來做Mqtt服務的轉發。

後面想著既然要用客戶端,那就順路封裝一個服務端吧,於是有了這篇文章。

 

先說環境

 <TargetFramework>net6.0</TargetFramework>

  <ItemGroup>
    <PackageReference Include="MQTTnet" Version="3.1.2" />
  </ItemGroup>

 

服務端呼叫示例

 1 //var server = new MqttServer(s =>
2 //{ 3 // s.ConnectionValidator = new MqttServerConnValidator { Port = 1884,}; 4 // //訊息回撥 5 // s.MessageReceived = s => 6 // { 7 // Console.WriteLine(s.Msg); 8 // }; 9 // //使用者連接回調 10 // s.ClientConnected = s => 11 // { 12 // Console.WriteLine(s.Msg); 13 // }; 14 // //使用者訂閱回撥
15 // s.SubscribedTopic = s => 16 // { 17 // Console.WriteLine(s.Msg); 18 // }; 19 //}, true);//直接啟動

服務端程式碼

  1 using MQTTnet;
  2 using MQTTnet.Protocol;
  3 using MQTTnet.Server;
  4 using System.Text;
  5 
  6 namespace MQTT
  7 {
  8     public class MqttServer
  9     {
 10         #region
Field Area 11 12 /// <summary> 13 /// Mqtt服務端 14 /// </summary> 15 private IMqttServer _mqttServer; 16 /// <summary> 17 /// MqttOptions 18 /// </summary> 19 private MqttServerOptions _options; 20 /// <summary> 21 /// Mqtt配置資訊 22 /// </summary> 23 private MqttServerConfig _mqttServerConfig; 24 25 #endregion 26 27 #region CTOR 28 29 /// <summary> 30 /// 呼叫示例 31 /// 32 /// var server = new MqttServer(s => 33 /// { 34 /// s.ConnectionValidator = new MqttServerConnValidator { Port = 1884,}; 35 /// //訊息回撥 36 /// s.MessageReceived = s => 37 /// { 38 /// Console.WriteLine(s.Msg); 39 /// }; 40 /// //使用者連接回調 41 /// s.ClientConnected = s => 42 /// { 43 /// Console.WriteLine(s.Msg); 44 /// }; 45 /// //使用者訂閱回撥 46 /// s.SubscribedTopic = s => 47 /// { 48 /// Console.WriteLine(s.Msg); 49 /// }; 50 /// }, true);//直接啟動 51 /// </summary> 52 public MqttServer() 53 { 54 Init(); 55 } 56 /// <summary> 57 /// MqttServer 58 /// 59 /// 呼叫示例 60 /// 61 /// var server = new MqttServer(s => 62 /// { 63 /// s.ConnectionValidator = new MqttServerConnValidator { Port = 1884,}; 64 /// //訊息回撥 65 /// s.MessageReceived = s => 66 /// { 67 /// Console.WriteLine(s.Msg); 68 /// }; 69 /// //使用者連接回調 70 /// s.ClientConnected = s => 71 /// { 72 /// Console.WriteLine(s.Msg); 73 /// }; 74 /// //使用者訂閱回撥 75 /// s.SubscribedTopic = s => 76 /// { 77 /// Console.WriteLine(s.Msg); 78 /// }; 79 /// }, true);//直接啟動 80 /// </summary> 81 /// <param name="mqConfig">配置回撥和引數</param> 82 /// <param name="autoStartMqtt">是否直接啟動mqtt服務</param> 83 public MqttServer(Action<MqttServerConfig> mqConfig, bool autoStartMqtt = false) 84 { 85 _mqttServerConfig = new MqttServerConfig(); 86 mqConfig(_mqttServerConfig); 87 Init(); 88 if (autoStartMqtt) 89 { 90 Start().Wait(); 91 } 92 } 93 94 #endregion 95 96 /// <summary> 97 /// 獲取例項 98 /// </summary> 99 /// <param name="mqConfig">MQTT配置</param> 100 /// <param name="autoStartMqtt">是否直接啟動</param> 101 /// <returns></returns> 102 public static MqttServer Instance(Action<MqttServerConfig> mqConfig, bool autoStartMqtt = false) 103 { 104 return new MqttServer(mqConfig, autoStartMqtt); 105 } 106 107 /// <summary> 108 /// 初始化MQTT 109 /// </summary> 110 private void Init() 111 { 112 try 113 { 114 #region Validator 115 116 if (_mqttServerConfig.ConnectionValidator != null) 117 { 118 //驗證客戶端資訊比如客戶Id、使用者名稱、密碼 119 _options = new MqttServerOptions 120 { 121 //連線驗證 122 ConnectionValidator = new MqttServerConnectionValidatorDelegate(p => 123 { 124 if (_mqttServerConfig.ConnectionValidator.ClientIds != null && 125 _mqttServerConfig.ConnectionValidator.ClientIds.Count > 0) 126 { 127 if (_mqttServerConfig.ConnectionValidator.ClientIds.First(s => s.Equals(p.ClientId)) is null) 128 { 129 p.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid; 130 } 131 } 132 133 if (_mqttServerConfig.ConnectionValidator.Usernames != null && 134 _mqttServerConfig.ConnectionValidator.Passwords != null && 135 _mqttServerConfig.ConnectionValidator.Usernames.Count > 0 && 136 _mqttServerConfig.ConnectionValidator.Passwords.Count > 0) 137 { 138 if (_mqttServerConfig.ConnectionValidator.Usernames.First(s => s.Equals(p.Username)) is null || 139 _mqttServerConfig.ConnectionValidator.Usernames.First(s => s.Equals(p.Username)) is null) 140 { 141 p.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; 142 } 143 } 144 145 }), 146 }; 147 if (_mqttServerConfig.ConnectionValidator.Port > 0) 148 { 149 //驗證客戶端埠和伺服器埠是否一致(不一致則不能連線到伺服器成功) 150 _options.DefaultEndpointOptions.Port = _mqttServerConfig.ConnectionValidator.Port; 151 } 152 } 153 else 154 { 155 _options = new MqttServerOptions(); 156 } 157 158 #endregion 159 160 #region Event Binding 161 162 //建立Mqtt伺服器 163 _mqttServer = new MqttFactory().CreateMqttServer(); 164 165 //開啟訂閱事件 166 _mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(MqttNetServer_SubscribedTopic); 167 168 //取消訂閱事件 169 _mqttServer.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(MqttNetServer_UnSubscribedTopic); 170 171 //客戶端訊息事件 172 _mqttServer.UseApplicationMessageReceivedHandler(MqttServe_ApplicationMessageReceived); 173 174 //客戶端連線事件 175 _mqttServer.UseClientConnectedHandler(MqttNetServer_ClientConnected); 176 177 //客戶端斷開事件 178 _mqttServer.UseClientDisconnectedHandler(MqttNetServer_ClientDisConnected); 179 180 #endregion 181 182 } 183 catch (Exception e) 184 { 185 if (_mqttServerConfig.ExceptionCallBack is null) 186 { 187 throw e; 188 } 189 _mqttServerConfig.ExceptionCallBack(e); 190 } 191 192 } 193 194 /// <summary> 195 /// //啟動伺服器 196 /// </summary> 197 /// <returns></returns> 198 public async Task Start() 199 => await _mqttServer.StartAsync(_options); 200 201 /// <summary> 202 /// 停止服務 203 /// </summary> 204 /// <returns></returns> 205 public async Task Stop() 206 => await _mqttServer.StopAsync(); 207 208 #region 內部事件轉換處理 209 210 /// <summary> 211 /// //客戶訂閱 212 /// </summary> 213 /// <param name="e"></param> 214 private void MqttNetServer_SubscribedTopic(MqttServerClientSubscribedTopicEventArgs e) 215 { 216 if (_mqttServerConfig.SubscribedTopic != null) 217 { 218 _mqttServerConfig.SubscribedTopic(new MqttServerRecive 219 { 220 ClientId = e.ClientId,//客戶端Id 221 Topic = e.TopicFilter.Topic, 222 Msg = $"客戶端[{ e.ClientId}]已訂閱主題:{e.TopicFilter.Topic}" 223 }); 224 } 225 } 226 227 /// <summary> 228 /// //客戶取消訂閱 229 /// </summary> 230 /// <param name="e"></param> 231 private void MqttNetServer_UnSubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e) 232 { 233 if (_mqttServerConfig.UnSubscribedTopic != null) 234 { 235 _mqttServerConfig.UnSubscribedTopic(new MqttServerRecive 236 { 237 ClientId = e.ClientId,//客戶端Id 238 Topic = e.TopicFilter, 239 Msg = $"客戶端[{ e.ClientId}]已取消訂閱主題:{e.TopicFilter}" 240 }); 241 } 242 } 243 244 /// <summary> 245 /// //接收訊息 246 /// </summary> 247 /// <param name="e"></param> 248 private void MqttServe_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e) 249 { 250 var Payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); 251 var Retain = e.ApplicationMessage.Retain; 252 if (_mqttServerConfig.MessageReceived != null) 253 { 254 _mqttServerConfig.MessageReceived(new MqttServerRecive 255 { 256 ClientId = e.ClientId,//客戶端Id 257 Topic = e.ApplicationMessage.Topic, 258 Payload = Payload, 259 Qos = e.ApplicationMessage.QualityOfServiceLevel, 260 Retain = e.ApplicationMessage.Retain, 261 Msg = $"客戶端[{e.ClientId}]>> 主題:[{e.ApplicationMessage.Topic}] " + 262 $"負載:[{Payload}] Qos:[{e.ApplicationMessage.QualityOfServiceLevel}] " + 263 $"保留:[{e.ApplicationMessage.Retain}]" 264 }); 265 } 266 } 267 268 /// <summary> 269 /// //客戶連線 270 /// </summary> 271 /// <param name="e"></param> 272 private void MqttNetServer_ClientConnected(MqttServerClientConnectedEventArgs e) 273 { 274 if (_mqttServerConfig.ClientConnected != null) 275 { 276 _mqttServerConfig.ClientConnected(new MqttServerRecive 277 { 278 ClientId = e.ClientId,//客戶端Id 279 Msg = $"客戶端[{ e.ClientId}]已連線" 280 }); 281 } 282 } 283 284 /// <summary> 285 /// //客戶連線斷開 286 /// </summary> 287 /// <param name="e"></param> 288 private void MqttNetServer_ClientDisConnected(MqttServerClientDisconnectedEventArgs e) 289 { 290 if (_mqttServerConfig.ClientDisConnected != null) 291 { 292 _mqttServerConfig.ClientDisConnected(new MqttServerRecive 293 { 294 ClientId = e.ClientId,//客戶端Id 295 Msg = $"客戶端[{ e.ClientId}]已斷開連線" 296 }); 297 } 298 } 299 300 #endregion 301 } 302 303 public class MqttServerConfig 304 { 305 /// <summary> 306 /// Mqtt驗證 307 /// </summary> 308 public MqttServerConnValidator ConnectionValidator = null; 309 /// <summary> 310 /// 客戶訂閱資訊提醒 311 /// </summary> 312 public Action<MqttServerRecive> SubscribedTopic = null; 313 /// <summary> 314 /// 客戶取消訂閱提醒 315 /// </summary> 316 public Action<MqttServerRecive> UnSubscribedTopic = null; 317 /// <summary> 318 /// 接收訊息 319 /// </summary> 320 public Action<MqttServerRecive> MessageReceived = null; 321 /// <summary> 322 /// 客戶連線提醒 323 /// </summary> 324 public Action<MqttServerRecive> ClientConnected = null; 325 /// <summary> 326 /// 客戶連線斷開提醒 327 /// </summary> 328 public Action<MqttServerRecive> ClientDisConnected = null; 329 /// <summary> 330 /// 異常資訊回撥(建議設定) 331 /// </summary> 332 public Action<Exception> ExceptionCallBack = null; 333 } 334 335 public class MqttServerConnValidator 336 { 337 /// <summary> 338 /// Connecte Client Id 339 /// </summary> 340 public IList<string> ClientIds { get; set; } 341 342 /// <summary> 343 /// Verify Username 344 /// </summary> 345 public IList<string> Usernames { get; set; } 346 347 /// <summary> 348 /// Verify Password 349 /// </summary> 350 public IList<string> Passwords { get; set; } 351 352 /// <summary> 353 /// Verify Port 354 /// </summary> 355 public int Port { get; set; } 356 } 357 358 public class MqttServerRecive 359 { 360 /// <summary> 361 /// 客戶端ID 362 /// </summary> 363 public string ClientId { get; set; } 364 /// <summary> 365 /// 主題 366 /// </summary> 367 public string Topic { get; set; } 368 /// <summary> 369 /// 負載/訊息 370 /// </summary> 371 public string Payload { get; set; } 372 /// <summary> 373 /// Qos 374 /// </summary> 375 public MqttQualityOfServiceLevel Qos { get; set; } 376 /// <summary> 377 /// 保留 378 /// </summary> 379 public bool Retain { get; set; } 380 /// <summary> 381 /// 訊息內容 382 /// </summary> 383 public string Msg { get; set; } 384 } 385 }
MQTT Server

客戶端呼叫示例

 1 //var client = new MqttClient(s =>
 2 //{
 3 //    s.Port = 1883;
 4 //    s.ServerIp = "127.0.0.1";
 5 //    s.UserName = "mqtt-test";
 6 //    s.Password = "mqtt-test";
 7 //    s.ReciveMsgCallback = s =>
 8 //    {
 9 //        Console.WriteLine(s.Payload_UTF8);
10 //    };
11 //}, true);
12 //client.Subscribe("/iot/");

客戶端程式碼

  1 using MQTTnet;
  2 using MQTTnet.Client;
  3 using MQTTnet.Client.Disconnecting;
  4 using MQTTnet.Client.Options;
  5 using MQTTnet.Protocol;
  6 using System.Text;
  7 
  8 namespace MQTT
  9 {
 10     public class MqttClient
 11     {
 12         #region Field Area
 13 
 14         /// <summary>
 15         /// Mqtt factory
 16         /// </summary>
 17         private MqttFactory _factory;
 18         /// <summary>
 19         /// Mqtt client
 20         /// </summary>
 21         private IMqttClient _mqttClient;
 22         /// <summary>
 23         /// Mqtt 配置資訊
 24         /// </summary>
 25         private MqttClientConfig _mqttClientConfig;
 26         /// <summary>
 27         /// Mqtt options
 28         /// </summary>
 29         private IMqttClientOptions _options;
 30 
 31         #endregion
 32 
 33         #region CTOR
 34 
 35         /// <summary>
 36         /// 預設啟動IP為127.0.0.1 埠為1883
 37         /// </summary>
 38         public MqttClient()
 39         {
 40             _mqttClientConfig = new MqttClientConfig
 41             {
 42                 ServerIp = "127.0.0.1",
 43                 Port = 1883
 44             };
 45             Init();
 46         }
 47         /// <summary>
 48         /// 呼叫示例
 49         /// 
 50         /// //var client = new MqttClient(s =>
 51         ///    {
 52         ///        s.Port = 1883;
 53         ///        s.ServerIp = "127.0.0.1";
 54         ///        s.UserName = "mqtt-test";
 55         ///        s.Password = "mqtt-test";
 56         ///        s.ReciveMsgCallback = s =>
 57         ///        {
 58         ///            Console.WriteLine(s.Payload_UTF8);
 59         ///        };
 60         ///    }, true);
 61         ///    client.Subscribe("/TopicName/");
 62         /// </summary>
 63         /// <param name="config">客戶端配置資訊</param>
 64         /// <param name="autoStart">直接啟動</param>
 65         public MqttClient(Action<MqttClientConfig> config, bool autoStart = false)
 66         {
 67             _mqttClientConfig = new MqttClientConfig();
 68             config(_mqttClientConfig);
 69             Init();
 70             if (autoStart)
 71             {
 72                 Start();
 73             }
 74         }
 75 
 76         #endregion
 77 
 78         /// <summary>
 79         /// 獲取MqttClient例項
 80         /// 
 81         /// 呼叫示例
 82         ///    //var client = MqttClient.Instance(s =>
 83         ///    {
 84         ///        s.Port = 1883;
 85         ///        s.ServerIp = "127.0.0.1";
 86         ///        s.UserName = "mqtt-test";
 87         ///        s.Password = "mqtt-test";
 88         ///        s.ReciveMsgCallback = s =>
 89         ///        {
 90         ///            Console.WriteLine(s.Payload_UTF8);
 91         ///        };
 92         ///    }, true);
 93         ///    client.Subscribe("/TopicName/");
 94         /// </summary>
 95         /// <param name="config">客戶端配置資訊</param>
 96         /// <param name="autoStart">直接啟動</param>
 97         /// <returns></returns>
 98         public static MqttClient Instance(Action<MqttClientConfig> config, bool autoStart = false)
 99             => new MqttClient(config, autoStart);
100 
101         /// <summary>
102         /// 初始化註冊
103         /// </summary>
104         private void Init()
105         {
106             try
107             {
108                 _factory = new MqttFactory();
109 
110                 _mqttClient = _factory.CreateMqttClient();
111 
112                 _options = new MqttClientOptionsBuilder()
113                     .WithTcpServer(_mqttClientConfig.ServerIp, _mqttClientConfig.Port)
114                     .WithCredentials(_mqttClientConfig.UserName, _mqttClientConfig.Password)
115                     .WithClientId(_mqttClientConfig.ClientId)
116                     .Build();
117 
118                 //訊息回撥
119                 _mqttClient.UseApplicationMessageReceivedHandler(ReciveMsg);
120             }
121             catch (Exception exp)
122             {
123                 if (_mqttClientConfig.Exception is null)
124                 {
125                     throw exp;
126                 }
127                 _mqttClientConfig.Exception(exp);
128             }
129         }
130 
131         #region 內部事件轉換處理
132 
133         /// <summary>
134         /// 訊息接收回調
135         /// </summary>
136         /// <param name="e"></param>
137         /// <returns></returns>
138         private void ReciveMsg(MqttApplicationMessageReceivedEventArgs e)
139         {
140             if (_mqttClientConfig.ReciveMsgCallback != null)
141             {
142                 _mqttClientConfig.ReciveMsgCallback(new MqttClientReciveMsg
143                 {
144                     Topic = e.ApplicationMessage.Topic,
145                     Payload_UTF8 = Encoding.UTF8.GetString(e.ApplicationMessage.Payload),
146                     Payload = e.ApplicationMessage.Payload,
147                     Qos = e.ApplicationMessage.QualityOfServiceLevel,
148                     Retain = e.ApplicationMessage.Retain,
149                 });
150             }
151         }
152 
153         /// <summary>
154         /// 訂閱
155         /// </summary>
156         /// <param name="topicName"></param>
157         public async void Subscribe(string topicName)
158         {
159             topicName = topicName.Trim();
160             if (string.IsNullOrEmpty(topicName))
161             {
162                 throw new Exception("訂閱主題不能為空!");
163             }
164 
165             if (!_mqttClient.IsConnected)
166             {
167                 throw new Exception("MQTT客戶端尚未連線!請先啟動連線");
168             }
169             await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topicName).Build());
170         }
171 
172         /// <summary>
173         /// 取消訂閱
174         /// </summary>
175         /// <param name="topicName"></param>
176         public async void Unsubscribe(string topicName)
177         {
178             topicName = topicName.Trim();
179             if (string.IsNullOrEmpty(topicName))
180             {
181                 throw new Exception("訂閱主題不能為空!");
182             }
183 
184             if (!_mqttClient.IsConnected)
185             {
186                 throw new Exception("MQTT客戶端尚未連線!請先啟動連線");
187             }
188             await _mqttClient.UnsubscribeAsync(topicName);
189         }
190 
191         /// <summary>
192         /// 重連機制
193         /// </summary>
194         private void ReConnected()
195         {
196             if (_mqttClient.IsConnected)
197             {
198                 return;
199             }
200             for (int i = 0; i < 10; i++)
201             {
202                 //重連機制
203                 _mqttClient.UseDisconnectedHandler(async e =>
204                 {
205                     try
206                     {
207                         await Task.Delay(TimeSpan.FromSeconds(_mqttClientConfig.ReconneTime));
208                         await _mqttClient.ConnectAsync(_options);
209                         return;
210                     }
211                     catch (Exception exp)
212                     {
213                         if (_mqttClientConfig.Exception is null)
214                         {
215                             throw exp;
216                         }
217                         _mqttClientConfig.Exception(exp);
218                     }
219                 });
220             }
221         }
222 
223         #endregion
224 
225         #region 訊息傳送
226 
227         /// <summary>
228         /// 傳送訊息,含有重連機制,如掉線會自動重連
229         /// </summary>
230         /// <param name="message"></param>
231         private async Task PublishAsync(string topicName, MqttApplicationMessageBuilder MessageBuilder, PublicQos qos = 0)
232         {
233             string topic = topicName.Trim();
234             if (string.IsNullOrEmpty(topic))
235             {
236                 throw new Exception("主題不能為空!");
237             }
238             ReConnected();
239 
240             MessageBuilder.WithTopic(topic).WithRetainFlag();
241             if (qos == PublicQos.Qos_0)
242             {
243                 MessageBuilder.WithAtLeastOnceQoS();
244             }
245             else if (qos == PublicQos.Qos_1)
246             {
247                 MessageBuilder.WithAtMostOnceQoS();
248             }
249             else
250             {
251                 MessageBuilder.WithExactlyOnceQoS();
252             }
253             var Message = MessageBuilder.Build();
254             try
255             {
256                 await _mqttClient.PublishAsync(Message);
257             }
258             catch (Exception e)
259             {
260                 if (_mqttClientConfig.Exception is null)
261                 {
262                     throw e;
263                 }
264                 _mqttClientConfig.Exception(e);
265             }
266 
267         }
268 
269         /// <summary>
270         /// 傳送訊息,含有重連機制,如掉線會自動重連
271         /// </summary>
272         /// <param name="message">文字訊息</param>
273         public async Task Publish(string topicName, string message, PublicQos qos = 0)
274         {
275             await PublishAsync(topicName, new MqttApplicationMessageBuilder()
276                 .WithPayload(message), qos);
277         }
278         /// <summary>
279         /// 傳送訊息,含有重連機制,如掉線會自動重連
280         /// </summary>
281         /// <param name="message">訊息流</param>
282         public async void Publish(string topicName, Stream message, PublicQos qos = 0)
283             => await PublishAsync(topicName, new MqttApplicationMessageBuilder()
284                 .WithPayload(message), qos);
285 
286         /// <summary>
287         /// 傳送訊息,含有重連機制,如掉線會自動重連
288         /// </summary>
289         /// <param name="message">Byte訊息</param>
290         public async void Publish(string topicName, IEnumerable<byte> message, PublicQos qos = 0)
291             => await PublishAsync(topicName, new MqttApplicationMessageBuilder()
292                 .WithPayload(message), qos);
293 
294         /// <summary>
295         /// 傳送訊息,含有重連機制,如掉線會自動重連
296         /// </summary>
297         /// <param name="message">Byte訊息</param>
298         public async void Publish(string topicName, byte[] message, PublicQos qos = 0)
299             => await PublishAsync(topicName, new MqttApplicationMessageBuilder()
300                 .WithPayload(message), qos);
301 
302         #endregion
303 
304         /// <summary>
305         /// 啟動服務
306         /// </summary>
307         /// <returns></returns>
308         public async Task Start()
309             => await _mqttClient.ConnectAsync(_options);
310 
311         /// <summary>
312         /// 停止服務
313         /// </summary>
314         /// <returns></returns>
315         public async Task Stop()
316             => await _mqttClient.DisconnectAsync(new MqttClientDisconnectOptions { ReasonCode = MqttClientDisconnectReason.NormalDisconnection}, CancellationToken.None);
317 
318     }
319     public class MqttClientConfig
320     {
321         private string _serverIp;
322         /// <summary>
323         /// 伺服器IP
324         /// </summary>
325         public string ServerIp
326         {
327             get => _serverIp;
328             set
329             {
330                 if (string.IsNullOrEmpty(value.Trim()))
331                 {
332                     throw new ArgumentException("ServerIp can't be null or empty!");
333                 }
334                 _serverIp = value;
335             }
336         }
337         private int _port;
338         /// <summary>
339         /// 伺服器埠
340         /// </summary>
341         public int Port
342         {
343             get => _port;
344             set
345             {
346                 if (value <= 0)
347                 {
348                     throw new ArgumentException("Port can't below the zero!");
349                 }
350                 _port = value;
351             }
352         }
353 
354         /// <summary>
355         /// 使用者名稱
356         /// </summary>
357         public string UserName { get; set; }
358         /// <summary>
359         /// 密碼
360         /// </summary>
361         public string Password { get; set; }
362 
363         private string _clientId;
364         /// <summary>
365         /// 唯一使用者ID,預設使用Guid
366         /// </summary>
367         public string ClientId
368         {
369             get
370             {
371                 _clientId = _clientId ?? Guid.NewGuid().ToString();
372                 return _clientId;
373             }
374             set => _clientId = value;
375         }
376         /// <summary>
377         /// 客戶端掉線重連時間,單位/s,預設5s
378         /// </summary>
379         public double ReconneTime { get; set; } = 5;
380         /// <summary>
381         /// 異常回調,預設為空,為空拋異常
382         /// </summary>
383         public Action<Exception> Exception = null;
384 
385         /// <summary>
386         /// 接收訊息回撥,預設不接收
387         /// </summary>
388         public Action<MqttClientReciveMsg> ReciveMsgCallback = null;
389     }
390     public class MqttClientReciveMsg
391     {
392         /// <summary>
393         /// 主題
394         /// </summary>
395         public string Topic { get; set; }
396         /// <summary>
397         /// UTF-8格式下的 負載/訊息
398         /// </summary>
399         public string Payload_UTF8 { get; set; }
400         /// <summary>
401         /// 原始 負載/訊息
402         /// </summary>
403         public byte[] Payload { get; set; }
404         /// <summary>
405         /// Qos
406         /// </summary>
407         public MqttQualityOfServiceLevel Qos { get; set; }
408         /// <summary>
409         /// 保留
410         /// </summary>
411         public bool Retain { get; set; }
412     }
413     public enum PublicQos
414     {
415         /// <summary>
416         /// //At most once,至多一次
417         /// </summary>
418         Qos_0,
419         /// <summary>
420         /// //At least once,至少一次
421         /// </summary>
422         Qos_1,
423         /// <summary>
424         /// //QoS2,Exactly once
425         /// </summary>
426         Qos_2,
427     }
428 }
MQTT Client

 

所有的支援類都在裡面,隨用隨跑。