C# Mqtt 断线重连

在通过 MqttClient 客户端连接之后,在服务端服务重启时,客户端如果没有重连机制,则无法再接收到订阅的消息。

使用的 Mqtt 组件为:M2Mqtt.Net.dll

一些特性发现

(1)如果提供的服务端地址是不可解析的,会引发异常无法实例化 MqttClient 对象。
(2)Connect 无法连接时会引发异常,IsConnected 为 false。
(3)服务端断开会触发客户端的 ConnectionClosed 事件,IsConnected 为 false。
(4)重新 Connect 需要重新 Subscribe 订阅主题。
(5)MqttClient.Subscribe 第一个参数为订阅主题数组,第二个为相应的 qosLevel,两个数组长度必须一致,否则会异常。

重连流程控制

主要代码实现

(1)线程主体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 自动重连主体
private void _TryContinueConnect()
{
    if (IsConnected) return;
 
    Thread retryThread = new Thread(new ThreadStart(delegate
    {
        while (_MqttClient == null || !_MqttClient.IsConnected)
        {
            if (_ToClose) break;
 
            if (_MqttClient == null)
            {
                _BuildClient();
                Thread.Sleep(3000);
                continue;
            }
 
            try
            {
                _TryCount++;
                _Connect();
            }
            catch (Exception ce)
            {
                Debug.WriteLine("re connect exception:" + ce.Message);
            }
 
            // 如果还没连接不符合结束条件则睡2秒
            if (!_MqttClient.IsConnected)
            {
                Thread.Sleep(2000);
            }
        }
    }));
             
    retryThread.Start();
}

 (2)实例化部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 实例化客户端
private void _BuildClient()
{
    try
    {
        _MqttClient = new MqttClient(_MqttServer);
    }
    catch (Exception e)
    {
        Debug.WriteLine("build client error:" + e.Message);
        return;
    }
 
    // 消息到达事件绑定
    _MqttClient.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
 
    // 连接断开事件绑定
    _MqttClient.ConnectionClosed += (sender, e) =>
    {
        if (!_ToClose)
        {
            // 尝试重连
            _TryContinueConnect();
        }
    };
}

 (3)尝试连接部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 发起一次连接,连接成功则订阅相关主题
private void _Connect()
{
    if (String.IsNullOrEmpty(_MqttUsername))
    {
        var b = _MqttClient.Connect(_MqttClientId);
    }
    else
    {
        var b = _MqttClient.Connect(_MqttClientId, _MqttUsername, _MqttUserpass);
    }
 
    if (_MqttClient.IsConnected)
    {
        _MqttClient.Subscribe(new string[] { "topic1", "topic2" },
            new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE });
    }
}

 

posted @   进步者One  阅读(4899)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示