通讯 --- C# .NET CORE MQTT 心跳服务

MQTT 服务可以自行学习,这里只是记录一下写的结果,粘贴即用。

首先引入包 MQTTnet ,注意 这个包这里的代码 是 4.0一下版本 我用的 3.1.2 版本的 4.以上是另外的写法,该内容中4 不支持我  直接下降版本到3.1.2 可以了。

如果你一定要用4.0以上的包,不用往下看了。

 

服务端 :默认端口是1883 我这里用的 1881

    /// <summary>
    /// 心跳监听服务端 -- 监听客户端心跳
    /// </summary>
    public class MqttServerExample
    {
        public static void ServiceMQTT()
        {
            try
            {
                var optionsBuilder = new MqttServerOptionsBuilder()
                  .WithDefaultEndpoint()//允许你为 MQTT 服务器设置一个默认的终端。当客户端没有显式指定终端时,它将使用默认的终端来建立连接。
                  .WithDefaultEndpointPort(1881)
                  .WithConnectionValidator(context =>  //处理与客户端连接相关的逻辑
                  {
                    
                      //Console.WriteLine($"Client '{context.ClientId}' connected.");
                      return Task.CompletedTask;
                  })
                  .WithApplicationMessageInterceptor(context =>  //处理与应用消息相关的逻辑
                  { 
                      // 拦截应用消息的逻辑
                      //Console.WriteLine($"Received message from client '{context.ClientId}': {context.ApplicationMessage.Payload}");

                      //监听客户端消息主题-判断是哪个客户端,更新客户端连接最后时间
                      if (context.ApplicationMessage.Topic == "ClientHeartbeat_Task" && context.ApplicationMessage.Payload != null)
                      {  
                          MQTTClinetCacher.ProjectStatus.TaskProjectLastTime = DateTime.Now;//更新客户端心跳时间-如果这个时间计算超过固定时间则可认为客户端心跳异常!!该逻辑自行处理
                      }else
                      {
                          Console.WriteLine("");
                      }
                  });

                var mqttServer = new MqttFactory().CreateMqttServer();
                mqttServer.StartAsync(optionsBuilder.Build());//启动MQTT服务

            }
            catch (Exception ex)
            {
                Log.Error($"MQTT Service ERR {ex.Message}");
            }
         
        }
    
    }

 

 

客户端

public class MqttClientExample
    {
        private static IMqttClient client  = new MqttFactory().CreateMqttClient();

        public static void StartMQTTClinet()
        {
            TryConnect();
        }

        public static async Task ConnectAndPublishWithHeartbeat()
        {
            try
            {
                 var options = new MqttClientOptionsBuilder()
                    .WithTcpServer("127.0.0.1", 1881)
                    .WithClientId("ClientHeartbeat_Task")
                    .WithCleanSession()
                    .Build();

                client.UseConnectedHandler(async e =>
                {
                    await Task.Delay(TimeSpan.FromSeconds(1));
 
                    while (true)
                    {
                        await Task.Delay(TimeSpan.FromSeconds(1));//延迟时间1秒
                        //.WithTopic("heartbeat"): 设置消息的主题为 "heartbeat",这是消息在 MQTT 中进行发布和订阅时的标识。
                        //.WithPayload("ping"): 设置消息的有效负载(Payload)为 "ping",即要发送的数据内容。
                        //.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce): 设置消息的 QoS 级别为至少一次传输,这意味着消息会确保至少被送达一次,但可能会重复传输。
                        //.WithRetainFlag(): 启用消息的保留标志(Retain Flag),当有新的订阅者加入时,会立即将最新的保留消息推送给它们。
                        //.Build(): 构建最终的 MQTT 应用消息对象。
                        var heartbeatMessage = new MqttApplicationMessageBuilder()
                            .WithTopic("ClientHeartbeat_Task")
                            .WithPayload("ClientHeartbeat TaskProject OK")
                            .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
                            .WithRetainFlag()
                            .Build();

                        await client.PublishAsync(heartbeatMessage);// 发布消息
                        Console.WriteLine($"SEND SERVICE Task {DateTime.Now.ToString()}");
                    }
                });

                await client.ConnectAsync(options);// 发布消息
                Console.ReadLine();
                //await client.DisconnectAsync(); // 断开与 MQTT 服务器的连接
            }
            catch (Exception ex)
            { 

            } 
        }

        /// <summary>
        /// 断线重连
        /// </summary>
        static void TryConnect()
        {
            Thread thread = new Thread(async () =>
            {
                while (true)
                {
                    Thread.Sleep(2 * 1000);
                    if (!client.IsConnected)
                    {
                        Console.WriteLine($"SEND SERVICE Try Connetc Task {DateTime.Now.ToString()}");
                        await ConnectAndPublishWithHeartbeat();
                    }
                }
            });
            thread.Start();
        }


    }

 

缓存类

    public class MQTTClinetCacher
    {
        public static MQTTClientStatus ProjectStatus = new MQTTClientStatus();
    }

    public class MQTTClientStatus
    { 

        public DateTime TaskProjectLastTime { get; set; }
         
    }

 

最后判断 如果 MQTTClinetCacher.TaskProjectLastTime 与当前时间差大于5秒则认为 超时

        public static int TimeDifferenceInSeconds(DateTime startTime)
        {
            TimeSpan timeDifference = DateTime.Now - startTime;
            int seconds = (int)timeDifference.TotalSeconds;
            return seconds;
        }

TimeDifferenceInSeconds(MQTTClinetCacher.ProjectStatus.TaskProjectLastTime) > 5

 

posted @ 2023-09-09 14:54  #青鸟爱吃鱼  阅读(843)  评论(0编辑  收藏  举报