通讯 --- 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