MqttClient.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. using System.Security.Authentication;
  2. using MqttConsoleAppClient;
  3. using MQTTnet;
  4. using MQTTnet.Client;
  5. using MQTTnet.Formatter;
  6. namespace MQTTnet.Samples.Client;
  7. public static class Client_Connection_Samples
  8. {
  9. public static async Task Connect_Client()
  10. {
  11. /*
  12. * This sample creates a simple MQTT client and connects to a public broker.
  13. *
  14. * Always dispose the client when it is no longer used.
  15. * The default version of MQTT is 3.1.1.
  16. */
  17. var mqttFactory = new MqttFactory();
  18. using (var mqttClient = mqttFactory.CreateMqttClient())
  19. {
  20. // Use builder classes where possible in this project.
  21. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build();
  22. // This will throw an exception if the server is not available.
  23. // The result from this message returns additional data which was sent
  24. // from the server. Please refer to the MQTT protocol specification for details.
  25. var response = await mqttClient.ConnectAsync(mqttClientOptions);
  26. mqttClient.PublishAsync(new MqttApplicationMessage() { });
  27. mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
  28. Console.WriteLine("The MQTT client is connected.");
  29. response.DumpToConsole();
  30. Console.ReadLine();
  31. // Send a clean disconnect to the server by calling _DisconnectAsync_. Without this the TCP connection
  32. // gets dropped and the server will handle this as a non clean disconnect (see MQTT spec for details).
  33. //var mqttClientDisconnectOptions = mqttFactory.CreateClientDisconnectOptionsBuilder().Build();
  34. //await mqttClient.DisconnectAsync(mqttClientDisconnectOptions, CancellationToken.None);
  35. }
  36. }
  37. private static Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
  38. {
  39. throw new NotImplementedException();
  40. }
  41. public static async Task Connect_Client_Timeout()
  42. {
  43. /*
  44. * This sample creates a simple MQTT client and connects to an invalid broker using a timeout.
  45. *
  46. * This is a modified version of the sample _Connect_Client_! See other sample for more details.
  47. */
  48. var mqttFactory = new MqttFactory();
  49. using (var mqttClient = mqttFactory.CreateMqttClient())
  50. {
  51. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build();
  52. try
  53. {
  54. using (var timeoutToken = new CancellationTokenSource(TimeSpan.FromHours(1)))
  55. {
  56. await mqttClient.ConnectAsync(mqttClientOptions, timeoutToken.Token);
  57. }
  58. }
  59. catch (OperationCanceledException)
  60. {
  61. Console.WriteLine("Timeout while connecting.");
  62. }
  63. }
  64. }
  65. public static async Task Connect_Client_Using_MQTTv5()
  66. {
  67. /*
  68. * This sample creates a simple MQTT client and connects to a public broker using MQTTv5.
  69. *
  70. * This is a modified version of the sample _Connect_Client_! See other sample for more details.
  71. */
  72. var mqttFactory = new MqttFactory();
  73. using (var mqttClient = mqttFactory.CreateMqttClient())
  74. {
  75. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").WithProtocolVersion(MqttProtocolVersion.V500).Build();
  76. // In MQTTv5 the response contains much more information.
  77. var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
  78. Console.WriteLine("The MQTT client is connected.");
  79. response.DumpToConsole();
  80. }
  81. }
  82. public static async Task Connect_Client_Using_TLS_1_2()
  83. {
  84. /*
  85. * This sample creates a simple MQTT client and connects to a public broker using TLS 1.2 encryption.
  86. *
  87. * This is a modified version of the sample _Connect_Client_! See other sample for more details.
  88. */
  89. var mqttFactory = new MqttFactory();
  90. using (var mqttClient = mqttFactory.CreateMqttClient())
  91. {
  92. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io")
  93. .WithTls(
  94. o =>
  95. {
  96. // The used public broker sometimes has invalid certificates. This sample accepts all
  97. // certificates. This should not be used in live environments.
  98. o.CertificateValidationHandler = _ => true;
  99. // The default value is determined by the OS. Set manually to force version.
  100. o.SslProtocol = SslProtocols.Tls12;
  101. })
  102. .Build();
  103. using (var timeout = new CancellationTokenSource(5000))
  104. {
  105. await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
  106. Console.WriteLine("The MQTT client is connected.");
  107. }
  108. }
  109. }
  110. public static async Task Connect_Client_Using_WebSockets()
  111. {
  112. /*
  113. * This sample creates a simple MQTT client and connects to a public broker using a WebSocket connection.
  114. *
  115. * This is a modified version of the sample _Connect_Client_! See other sample for more details.
  116. */
  117. var mqttFactory = new MqttFactory();
  118. using (var mqttClient = mqttFactory.CreateMqttClient())
  119. {
  120. var mqttClientOptions = new MqttClientOptionsBuilder().WithWebSocketServer("broker.hivemq.com:8000/mqtt").Build();
  121. var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
  122. Console.WriteLine("The MQTT client is connected.");
  123. response.DumpToConsole();
  124. }
  125. }
  126. public static async Task Connect_Client_With_TLS_Encryption()
  127. {
  128. /*
  129. * This sample creates a simple MQTT client and connects to a public broker with enabled TLS encryption.
  130. *
  131. * This is a modified version of the sample _Connect_Client_! See other sample for more details.
  132. */
  133. var mqttFactory = new MqttFactory();
  134. using (var mqttClient = mqttFactory.CreateMqttClient())
  135. {
  136. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 8883)
  137. .WithTls(
  138. o =>
  139. {
  140. // The used public broker sometimes has invalid certificates. This sample accepts all
  141. // certificates. This should not be used in live environments.
  142. o.CertificateValidationHandler = _ => true;
  143. })
  144. .Build();
  145. // In MQTTv5 the response contains much more information.
  146. using (var timeout = new CancellationTokenSource(5000))
  147. {
  148. var response = await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
  149. Console.WriteLine("The MQTT client is connected.");
  150. response.DumpToConsole();
  151. }
  152. }
  153. }
  154. public static async Task Inspect_Certificate_Validation_Errors()
  155. {
  156. /*
  157. * This sample prints the certificate information while connection. This data can be used to decide whether a connection is secure or not
  158. * including the reason for that status.
  159. */
  160. var mqttFactory = new MqttFactory();
  161. using (var mqttClient = mqttFactory.CreateMqttClient())
  162. {
  163. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io", 8883)
  164. .WithTls(
  165. o =>
  166. {
  167. o.CertificateValidationHandler = eventArgs =>
  168. {
  169. eventArgs.Certificate.Subject.DumpToConsole();
  170. eventArgs.Certificate.GetExpirationDateString().DumpToConsole();
  171. eventArgs.Chain.ChainPolicy.RevocationMode.DumpToConsole();
  172. eventArgs.Chain.ChainStatus.DumpToConsole();
  173. eventArgs.SslPolicyErrors.DumpToConsole();
  174. return true;
  175. };
  176. })
  177. .Build();
  178. // In MQTTv5 the response contains much more information.
  179. using (var timeout = new CancellationTokenSource(5000))
  180. {
  181. await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
  182. }
  183. }
  184. }
  185. public static async Task Ping_Server()
  186. {
  187. /*
  188. * This sample sends a PINGREQ packet to the server and waits for a reply.
  189. *
  190. * This is only supported in METTv5.0.0+.
  191. */
  192. var mqttFactory = new MqttFactory();
  193. using (var mqttClient = mqttFactory.CreateMqttClient())
  194. {
  195. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
  196. await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
  197. // This will throw an exception if the server does not reply.
  198. await mqttClient.PingAsync(CancellationToken.None);
  199. Console.WriteLine("The MQTT server replied to the ping request.");
  200. }
  201. }
  202. public static async Task Reconnect_Using_Event()
  203. {
  204. /*
  205. * This sample shows how to reconnect when the connection was dropped.
  206. * This approach uses one of the events from the client.
  207. * This approach has a risk of dead locks! Consider using the timer approach (see sample).
  208. */
  209. var mqttFactory = new MqttFactory();
  210. using (var mqttClient = mqttFactory.CreateMqttClient())
  211. {
  212. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
  213. mqttClient.DisconnectedAsync += async e =>
  214. {
  215. if (e.ClientWasConnected)
  216. {
  217. // Use the current options as the new options.
  218. await mqttClient.ConnectAsync(mqttClient.Options);
  219. }
  220. };
  221. await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
  222. }
  223. }
  224. public static void Reconnect_Using_Timer()
  225. {
  226. /*
  227. * This sample shows how to reconnect when the connection was dropped.
  228. * This approach uses a custom Task/Thread which will monitor the connection status.
  229. * This is the recommended way but requires more custom code!
  230. */
  231. var mqttFactory = new MqttFactory();
  232. using (var mqttClient = mqttFactory.CreateMqttClient())
  233. {
  234. var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
  235. _ = Task.Run(
  236. async () =>
  237. {
  238. // User proper cancellation and no while(true).
  239. while (true)
  240. {
  241. try
  242. {
  243. // This code will also do the very first connect! So no call to _ConnectAsync_ is required
  244. // in the first place.
  245. if (!mqttClient.IsConnected)
  246. {
  247. await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
  248. // Subscribe to topics when session is clean etc.
  249. Console.WriteLine("The MQTT client is connected.");
  250. }
  251. }
  252. catch
  253. {
  254. // Handle the exception properly (logging etc.).
  255. }
  256. finally
  257. {
  258. // Check the connection state every 5 seconds and perform a reconnect if required.
  259. await Task.Delay(TimeSpan.FromSeconds(5));
  260. }
  261. }
  262. });
  263. }
  264. }
  265. }