代码改变世界

.net core 使用MQTTNET搭建MQTT 服务以及客户端例子

2023-10-11 17:33  古兆洋  阅读(954)  评论(0编辑  收藏  举报

转自:https://blog.csdn.net/u011540323/article/details/103694675/

最近项目可能用到MQTT协议故而稍作研究了一下,MQTT协议,基于TCP封装的发布订阅的消息传递机制,理论详情可查看MQTT--入门_liefyuan的博客-CSDN博客_mqtt 这位老兄的总结,废话不多说,先上效果图。

 

采用.NET体系用的较多的MQTTNET 3.0版本实现,服务端代码如下

try
{
var options = new MqttServerOptions
{
//连接验证
ConnectionValidator = new MqttServerConnectionValidatorDelegate(p =>
{
if (p.ClientId == "SpecialClient")
{
if (p.Username != "USER" || p.Password != "PASS")
{
p.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
}
}
}),

// Storage = new RetainedMessageHandler(),

//消息拦截发送验证
ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(context =>
{
if (MqttTopicFilterComparer.IsMatch(context.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#"))
{
// Replace the payload with the timestamp. But also extending a JSON
// based payload with the timestamp is a suitable use case.
context.ApplicationMessage.Payload = Encoding.UTF8.GetBytes(DateTime.Now.ToString("O"));
}

if (context.ApplicationMessage.Topic == "not_allowed_topic")
{
context.AcceptPublish = false;
context.CloseConnection = true;
}
}),
///订阅拦截验证
SubscriptionInterceptor = new MqttServerSubscriptionInterceptorDelegate(context =>
{
if (context.TopicFilter.Topic.StartsWith("admin/foo/bar") && context.ClientId != "theAdmin")
{
context.AcceptSubscription = false;
}

if (context.TopicFilter.Topic.StartsWith("the/secret/stuff") && context.ClientId != "Imperator")
{
context.AcceptSubscription = false;
context.CloseConnection = true;
}
})
};

// Extend the timestamp for all messages from clients.
// Protect several topics from being subscribed from every client.

//var certificate = new X509Certificate(@"C:\certs\test\test.cer", "");
//options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert);
//options.ConnectionBacklog = 5;
//options.DefaultEndpointOptions.IsEnabled = true;
//options.TlsEndpointOptions.IsEnabled = false;

var mqttServer = new MqttFactory().CreateMqttServer();

mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e =>
{
Console.WriteLine(
$"'{e.ClientId}' reported '{e.ApplicationMessage.Topic}' > '{Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? new byte[0])}'",
ConsoleColor.Magenta);
});

//options.ApplicationMessageInterceptor = c =>
//{
// if (c.ApplicationMessage.Payload == null || c.ApplicationMessage.Payload.Length == 0)
// {
// return;
// }

// try
// {
// var content = JObject.Parse(Encoding.UTF8.GetString(c.ApplicationMessage.Payload));
// var timestampProperty = content.Property("timestamp");
// if (timestampProperty != null && timestampProperty.Value.Type == JTokenType.Null)
// {
// timestampProperty.Value = DateTime.Now.ToString("O");
// c.ApplicationMessage.Payload = Encoding.UTF8.GetBytes(content.ToString());
// }
// }
// catch (Exception)
// {
// }
//};


//开启订阅以及取消订阅
mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(MqttServer_SubscribedTopic);
mqttServer.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(MqttServer_UnSubscribedTopic);

//客户端连接事件
mqttServer.UseClientConnectedHandler( MqttServer_ClientConnected);

//客户端断开事件
mqttServer.UseClientDisconnectedHandler(MqttServer_ClientDisConnected);
await mqttServer.StartAsync(options);

Console.WriteLine("服务启动成功,输入任意内容并回车停止服务");
Console.ReadLine();

await mqttServer.StopAsync();
}
catch (Exception e)
{
Console.WriteLine(e);
}

Console.ReadLine();

客户端代码如下:

  1    // Create a new MQTT client.
  2             var factory = new MqttFactory();
  3             mqttClient = factory.CreateMqttClient();
  4             // Create TCP based options using the builder.
  5             var options = new MqttClientOptionsBuilder()
  6                 .WithClientId(clientId)
  7                 .WithCredentials(user, pwd)//用户名 密码
  8                 .WithCleanSession()
  9                   .WithTcpServer("127.0.0.1", 1883) // Port is optional TCP 服务
 10                                                     //      .WithTls(
 11                                                     //new MqttClientOptionsBuilderTlsParameters
 12                                                     //{
 13                                                     //    UseTls = true,
 14                                                     //    CertificateValidationCallback = (X509Certificate x, X509Chain y, SslPolicyErrors z, IMqttClientOptions o) =>
 15                                                     //    {
 16                                                     //        // TODO: Check conditions of certificate by using above parameters.
 17                                                     //        return true;
 18                                                     //    },
 19  
 20                 //})//类型 TCPS
 21                 .Build();
 22  
 23             //重连机制
 24             mqttClient.UseDisconnectedHandler(async e =>
 25                 {
 26                     Console.WriteLine("### DISCONNECTED FROM SERVER ###");
 27                     await Task.Delay(TimeSpan.FromSeconds(3));
 28  
 29                     try
 30                     {
 31                         await mqttClient.ConnectAsync(options, CancellationToken.None); // Since 3.0.5 with CancellationToken
 32                 }
 33                     catch
 34                     {
 35                         Console.WriteLine("### RECONNECTING FAILED ###");
 36                     }
 37                 });
 38  
 39             //消费消息
 40             mqttClient.UseApplicationMessageReceivedHandler(e =>
 41             {
 42                 Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
 43                 Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");//主题
 44                 Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");//页面信息
 45                 Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");//消息等级
 46                 Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");//是否保留
 47                 Console.WriteLine();
 48  
 49                 // Task.Run(() => mqttClient.PublishAsync("hello/world"));
 50             });
 51  
 52  
 53  
 54             //连接成功触发订阅主题
 55             mqttClient.UseConnectedHandler(async e =>
 56             {
 57                 Console.WriteLine($"### 成功连接 ###");
 58  
 59                 // Subscribe to a topic
 60                 //await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("my/topic").Build());
 61  
 62  
 63                 //Console.WriteLine("### SUBSCRIBED ###");
 64             });
 65  
 66             try
 67             {
 68  
 69                 await mqttClient.ConnectAsync(options, CancellationToken.None);
 70                 bool isExit = false;
 71                 while (!isExit)
 72                 {
 73                     Console.WriteLine(@"请输入
 74                     1.订阅主题
 75                     2.取消订阅
 76                     3.发送消息
 77                     4.退出输入exit");
 78                     var input = Console.ReadLine();
 79                     switch (input)
 80                     {
 81                         case "1":
 82                             Console.WriteLine(@"请输入主题名称:");
 83                             var topicName = Console.ReadLine();
 84                             await SubscribedTopic(topicName);
 85                             break;
 86                         case "2":
 87                             Console.WriteLine(@"请输入需要取消订阅主题名称:");
 88                             topicName = Console.ReadLine();
 89                             await UnsubscribedTopic(topicName);
 90                             break;
 91                         case "3":
 92                             Console.WriteLine("请输入需要发送的主题名称");
 93                             topicName = Console.ReadLine();
 94                             Console.WriteLine("请输入需要发送的消息");
 95                             var message = Console.ReadLine();
 96  
 97                             await PublishMessageAsync(new MQTTMessageModel() { Payload = message, Topic = topicName, Retain = true });
 98                             break;
 99                         case "exit":
100                             isExit = true;
101                             break;
102                         default:
103                             Console.WriteLine("请输入正确指令!");
104                             break;
105                     }
106                 }
107             }
108             catch (Exception ex)
109             {
110                 Console.WriteLine(ex.ToString());
111                 Console.ReadLine();
112             }

服务端以及客户端都是core 3.1需要的小伙伴可以下载完整例子参考。

https://download.csdn.net/download/u011540323/12050633
————————————————
版权声明:本文为CSDN博主「11eleven」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011540323/article/details/103694675/