用 TouchSocket.Mqtt 从 0 到 1:写一个真正能跑起来的 MQTT 服务端与客户端
若汝棋茗
2026年04月21日 10:52

如果你最近在做物联网、设备上报、消息推送、边缘网关,或者只是想给系统加一条“轻量、低延迟、天然支持发布订阅”的通道,那 MQTT 依然是一个非常稳的选择。

问题在于,很多人学 MQTT 时会遇到两个很烦的现实:

  1. 协议概念懂了,但落到代码里,不知道服务端和客户端到底怎么配。

  2. 好不容易连上了,接下来订阅、发布、重连、主题路由、WebSocket 接入,又是一堆零散知识点。

这篇文章就不讲空洞概念了。我们直接基于 TouchSocket.Mqtt,把一套完整的 MQTT 使用方式串起来:从 TCP 服务端、TCP 客户端,到插件收消息、主题路由、WebSocket MQTT,再到几个非常实用的踩坑提醒。

整篇文章内容,基于仓库里的这些真实代码整理而来:

  • examples/Mqtt/MqttConsoleApp/Program.cs

  • examples/Mqtt/MqttTopicHandlerConsoleApp/Program.cs

  • examples/Mqtt/MqttWebSocketConsoleApp/Program.cs

  • handbook/docs/mqttservice.mdx

  • handbook/docs/mqttclient.mdx

  • Src/TouchSocket.Mqtt/*

官方链接

  • 官网与文档首页:https://touchsocket.net/

  • GitHub:https://github.com/RRQM

  • Gitee:https://gitee.com/RRQM_Home

  • NuGet 包名:TouchSocket.Mqtt

安装命令很直接:

代码块
Shell
自动换行
复制代码
dotnet add package TouchSocket.Mqtt
复制成功

从当前工程源码可以看到,TouchSocket.Mqtt 支持的目标框架包括:

  • net462

  • netstandard2.0

  • netstandard2.1

  • net6.0

  • net8.0

  • net10.0

这意味着它不只是适合新项目,对不少历史项目也比较友好。

为什么值得先看 TouchSocket.Mqtt

基于当前源码和示例来看,TouchSocket.Mqtt 不是一个“只能发发消息”的轻包装,它提供的是一套相对完整的 MQTT 能力:

  • 支持 TCP 和 WebSocket 两种接入方式

  • 同时覆盖 MqttTcpService 与 MqttTcpClient

  • 支持 MQTT 3.1.1 和 5.0+

  • 支持标准的订阅、取消订阅、发布、QoS

  • 提供插件机制,方便监听连接和消息生命周期

  • 提供 UseMqttTopicHandler 做主题路由封装

  • 支持断线重连插件

  • 服务端可以主动广播消息

如果你已经在用 TouchSocket 体系做网络开发,那这套 MQTT 能力接入成本会非常低,写起来也符合 TouchSocket 一贯的配置风格。

先别急着写代码,先把角色看清楚

在这套库里,你可以把几个核心角色记住:

  • MqttTcpService 这是基于 TCP 的 MQTT 服务端,也就是 Broker。

  • MqttTcpClient 这是基于 TCP 的 MQTT 客户端,用来连接 Broker、订阅主题、发布消息。

  • HttpService + AddMqttWebSocketService + UseMqttWebSocket 这是基于 WebSocket 的 MQTT 服务端组合,适合浏览器或前端场景。

  • MqttWebSocketClient 这是基于 WebSocket 的 MQTT 客户端。

  • IMqttService 服务端统一能力接口,核心是 MqttBroker。

  • IMqttClient 客户端统一能力接口,核心方法包括:

    • PublishAsync

    • SubscribeAsync

    • UnsubscribeAsync

    • PingAsync

理解这几个角色后,下面的代码就很顺了。

一、5 分钟跑通:创建一个 TCP 版 MQTT 服务端

如果你只是想先把 Broker 立起来,最简单的方式就是直接使用 MqttTcpService。

代码块
C#
自动换行
复制代码
using TouchSocket.Core;
using TouchSocket.Mqtt;

var service = new MqttTcpService();

var config = new TouchSocketConfig()
    .SetListenIPHosts(7789)
    .ConfigureContainer(a =>
    {
        a.AddConsoleLogger();
    });

await service.SetupAsync(config);
await service.StartAsync();

Console.WriteLine("MQTT 服务端已启动,监听 tcp://127.0.0.1:7789");
复制成功

这段代码对应的思路非常清晰:

  1. 创建 MqttTcpService

  2. 用 TouchSocketConfig 配监听端口

  3. 注入日志

  4. SetupAsync

  5. StartAsync

对于入门来说,这已经足够了。

如果你之前写过原生 Socket 或手动拼 Broker,你会明显感受到这种写法的轻松程度。

二、创建一个 TCP 版 MQTT 客户端

服务端起来之后,我们再连接一个客户端。

代码块
C#
自动换行
复制代码
using TouchSocket.Core;
using TouchSocket.Mqtt;

var client = new MqttTcpClient();

var config = new TouchSocketConfig()
    .SetRemoteIPHost("tcp://127.0.0.1:7789")
    .SetMqttConnectOptions(options =>
    {
        options.ClientId = Guid.NewGuid().ToString("N");
        options.UserName = "TestUser";
        options.Password = "TestPassword";
        options.ProtocolName = "MQTT";
        options.Version = MqttProtocolVersion.V311;
        options.KeepAlive = 60;
        options.CleanSession = true;
    })
    .ConfigureContainer(a =>
    {
        a.AddConsoleLogger();
    });

await client.SetupAsync(config);
await client.ConnectAsync();

Console.WriteLine("客户端已连接");
复制成功

这里最值得注意的是 SetMqttConnectOptions。

它就是整个 MQTT 连接阶段的核心配置入口。根据源码中的 MqttConnectOptions,常用字段包括:

  • ClientId

  • UserName

  • Password

  • Version

  • KeepAlive

  • CleanSession

  • WillFlag

  • WillTopic

  • WillPayload

  • UserProperties

  • SessionExpiryInterval

  • ReceiveMaximum

  • MaximumPacketSize

也就是说,如果你后面要用 MQTT 5.0 的高级能力,大多数情况下也是从这里展开。

三、客户端订阅主题

连上 Broker 之后,下一步通常就是订阅。

TouchSocket.Mqtt 的订阅模型比较标准:你先构造 SubscribeRequest,再包装成 MqttSubscribeMessage,最后执行 SubscribeAsync。

代码块
C#
自动换行
复制代码
var topic1 = "sensor/temperature";
var topic2 = "sensor/humidity";

var subscribeRequest1 = new SubscribeRequest(topic1, QosLevel.AtLeastOnce);
var subscribeRequest2 = new SubscribeRequest(topic2, QosLevel.AtMostOnce);

var mqttSubscribeMessage = new MqttSubscribeMessage(subscribeRequest1, subscribeRequest2);
var mqttSubAckMessage = await client.SubscribeAsync(mqttSubscribeMessage);

foreach (var item in mqttSubAckMessage.ReturnCodes)
{
    Console.WriteLine($"订阅结果: {item}");
}
复制成功

这段 API 有两个优点:

  • 能一次订阅多个主题

  • 每个主题可以单独指定 QoS

如果你需要更细粒度的 MQTT 5.0 订阅控制,SubscribeRequest 还支持这些高级参数:

  • NoLocal

  • RetainAsPublished

  • RetainHandling

也就是说,它不只是“能订阅”,而是预留了比较完整的 MQTT 订阅语义。

四、客户端发布消息

订阅完成之后,自然就是发布消息。

最常用的写法如下:

代码块
C#
自动换行
复制代码
using System.Text;

var payload = Encoding.UTF8.GetBytes("Hello TouchSocket MQTT");

var message = new MqttPublishMessage(
    "sensor/temperature",
    false,
    QosLevel.AtLeastOnce,
    payload);

await client.PublishAsync(message);
复制成功

这里 4 个关键参数分别代表:

  • 主题名 TopicName

  • 是否保留消息 retain

  • QoS 等级

  • 消息体 payload

如果你还在区分 QoS 的使用场景,可以简单这么记:

  • AtMostOnce 追求吞吐,不太在乎偶发丢失

  • AtLeastOnce 大多数业务场景的均衡选择

  • ExactlyOnce 代价最高,适合对重复与丢失都极其敏感的场景

五、客户端怎么收消息:插件是关键

在 TouchSocket.Mqtt 里,消息接收主要不是靠你手写轮询,而是通过插件机制来接。

这也是这套库非常顺手的一点。

1. 只关心发布消息本身,用 IMqttReceivedPlugin

如果你只关心“收到了一条真正的业务消息”,那就监听 IMqttReceivedPlugin。

代码块
C#
自动换行
复制代码
using TouchSocket.Core;
using TouchSocket.Mqtt;

internal class MqttClientReceivedPlugin : PluginBase, IMqttReceivedPlugin
{
    public async Task OnMqttReceived(IMqttSession client, MqttReceivedEventArgs e)
    {
        var mqttMessage = e.MqttMessage;

        Console.WriteLine("收到发布消息: " + mqttMessage.TopicName);
        Console.WriteLine("QoS: " + mqttMessage.QosLevel);
        Console.WriteLine("Payload: " + Encoding.UTF8.GetString(mqttMessage.Payload.FirstSpan));

        await e.InvokeNext();
    }
}
复制成功

2. 想拦截所有 MQTT 报文,用 IMqttReceivingPlugin

如果你不只关心发布消息,还想看到订阅、取消订阅、确认报文等,就用 IMqttReceivingPlugin。

代码块
C#
自动换行
复制代码
internal class MqttClientReceivingPlugin : PluginBase, IMqttReceivingPlugin
{
    public async Task OnMqttReceiving(IMqttSession client, MqttReceivingEventArgs e)
    {
        Console.WriteLine("收到 MQTT 报文类型: " + e.MqttMessage.MessageType);
        await e.InvokeNext();
    }
}
复制成功

这两个插件的区别,建议你直接记一句话:

  • IMqttReceivedPlugin 看“业务消息”

  • IMqttReceivingPlugin 看“所有 MQTT 报文”

六、服务端怎么收消息

服务端的收消息方式和客户端高度一致,也是通过插件做。

例如,服务端监听所有 MQTT 报文:

代码块
C#
自动换行
复制代码
internal class MqttServerReceivingPlugin : PluginBase, IMqttReceivingPlugin
{
    public async Task OnMqttReceiving(IMqttSession client, MqttReceivingEventArgs e)
    {
        switch (e.MqttMessage)
        {
            case MqttSubscribeMessage subscribeMessage:
                foreach (var item in subscribeMessage.SubscribeRequests)
                {
                    Console.WriteLine($"客户端订阅主题: {item.Topic}, QoS: {item.QosLevel}");
                }
                break;

            case MqttUnsubscribeMessage unsubscribeMessage:
                foreach (var topic in unsubscribeMessage.TopicFilters)
                {
                    Console.WriteLine($"客户端取消订阅: {topic}");
                }
                break;
        }

        await e.InvokeNext();
    }
}
复制成功

如果你只想在服务端接收发布消息本身,同样可以用 IMqttReceivedPlugin。

代码块
C#
自动换行
复制代码
internal class MqttServerReceivedPlugin : PluginBase, IMqttReceivedPlugin
{
    public async Task OnMqttReceived(IMqttSession client, MqttReceivedEventArgs e)
    {
        Console.WriteLine("服务端收到消息: " + e.MqttMessage.TopicName);
        await e.InvokeNext();
    }
}
复制成功

这种设计非常适合做这些事情:

  • 审计某个客户端订阅了哪些主题

  • 记录发布轨迹

  • 做权限校验

  • 做消息监控

  • 对接业务日志系统

七、服务端主动向客户端广播消息

很多人以为 MQTT Broker 只能被动转发客户端消息,实际上在 TouchSocket.Mqtt 里,服务端自己也可以主动发消息。

关键入口就是 IMqttService.MqttBroker。

MqttTcpService 本身就实现了 IMqttService,所以你可以直接这样写:

代码块
C#
自动换行
复制代码
using System.Buffers;
using System.Text;

var broker = service.MqttBroker;

await broker.ForwardMessageAsync(
    new MqttArrivedMessage(
        "system/broadcast",
        QosLevel.AtLeastOnce,
        false,
        new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes("服务器主动广播"))));
复制成功

这在下面这些场景里非常有价值:

  • 服务端推送系统公告

  • 服务端主动下发控制命令

  • 后台任务完成后主动通知设备

  • 从数据库或消息队列读取内容后转发给 MQTT 客户端

八、管理客户端连接

作为服务端,除了收发消息,你通常还需要能看到当前有哪些客户端在线,以及必要时主动断开某个客户端。

当前示例里已经给出了非常直接的写法:

代码块
C#
自动换行
复制代码
foreach (var client in service.Clients)
{
    Console.WriteLine(client.Id);
}
复制成功

如果要踢掉某个客户端:

代码块
C#
自动换行
复制代码
foreach (var client in service.Clients)
{
    if (client.Id == "123")
    {
        await client.CloseAsync("normal close");
    }
}
复制成功

这意味着你可以很容易做出基础的 Broker 管理能力,比如:

  • 在线客户端列表

  • 指定客户端断开

  • 简单的后台运维页面

九、比手写订阅更舒服:UseMqttTopicHandler

如果你看过 examples/Mqtt/MqttTopicHandlerConsoleApp/Program.cs,会发现它演示了一个非常实用的能力:UseMqttTopicHandler。

这是我觉得这套 MQTT 代码里最适合写业务的一个点。

它的作用可以概括成一句话:

连接成功后自动订阅配置好的主题,并在收到消息后按主题规则自动分发到对应处理器。

换句话说,你不用每次都手写:

  • 连接成功后手动订阅

  • 收到消息后自己写 if/else 判断主题

你可以直接这样声明式配置:

代码块
C#
自动换行
复制代码
var subscriber = new MqttTcpClient();

await subscriber.SetupAsync(new TouchSocketConfig()
    .SetRemoteIPHost("127.0.0.1:7791")
    .SetMqttConnectOptions(options =>
    {
        options.ClientId = "subscriber-" + Guid.NewGuid().ToString("N");
        options.CleanSession = true;
        options.KeepAlive = 60;
        options.Version = MqttProtocolVersion.V311;
    })
    .ConfigurePlugins(a =>
    {
        a.UseMqttTopicHandler<MqttTcpClient>(opt =>
        {
            opt.AddSubscription("home/temperature", async (client, msg) =>
            {
                var text = Encoding.UTF8.GetString(msg.Payload.FirstSpan);
                Console.WriteLine($"收到消息 topic={msg.TopicName}, payload={text}");
                await Task.CompletedTask;
            });
        });
    }));
复制成功

为什么它特别适合业务开发

根据源码 MqttSubscriptionManagementPlugin<TClient> 的实现,它至少帮你做了两件事:

  1. 在 OnMqttConnected 后自动发起订阅

  2. 在 OnMqttReceived 时自动按主题匹配并路由到处理器

这就让你的代码结构会非常清晰:

  • 连接配置是连接配置

  • 主题声明是主题声明

  • 消息处理是消息处理

而不是全堆在一个大方法里。

十、主题通配符:+ 和 #

UseMqttTopicHandler 还有一个很适合写文章和业务示例的点,就是它支持 MQTT 的主题通配符。

1. 单级通配符 +

代码块
C#
自动换行
复制代码
a.UseMqttTopicHandler<MqttTcpClient>(opt =>
{
    opt.AddSubscription("home/+/temperature", async (client, msg) =>
    {
        Console.WriteLine($"命中单级通配符: {msg.TopicName}");
        await Task.CompletedTask;
    });
});
复制成功

这个规则可以匹配:

  • home/room1/temperature

  • home/room2/temperature

但不能匹配:

  • home/room1/device1/temperature

因为 + 只匹配一层。

2. 多级通配符 #

代码块
C#
自动换行
复制代码
a.UseMqttTopicHandler<MqttTcpClient>(opt =>
{
    opt.AddSubscription("home/#", async (client, msg) =>
    {
        Console.WriteLine($"命中多级通配符: {msg.TopicName}");
        await Task.CompletedTask;
    });
});
复制成功

这个规则就宽松很多,可以匹配:

  • home/temperature

  • home/room1/humidity

  • home/floor1/room2/light

如果你的设备主题层级很多,# 会非常好用。

十一、一个客户端同时订阅多个主题

在 UseMqttTopicHandler 模式下,多主题订阅的体验也很好。

代码块
C#
自动换行
复制代码
a.UseMqttTopicHandler<MqttTcpClient>(opt =>
{
    opt.AddSubscription("sensor/temperature", async (client, msg) =>
    {
        Console.WriteLine("温度: " + Encoding.UTF8.GetString(msg.Payload.FirstSpan));
        await Task.CompletedTask;
    })
    .AddSubscription("sensor/humidity", async (client, msg) =>
    {
        Console.WriteLine("湿度: " + Encoding.UTF8.GetString(msg.Payload.FirstSpan));
        await Task.CompletedTask;
    })
    .AddSubscription("sensor/pressure", QosLevel.AtLeastOnce, async (client, msg) =>
    {
        Console.WriteLine("气压: " + Encoding.UTF8.GetString(msg.Payload.FirstSpan));
        await Task.CompletedTask;
    });
});
复制成功

这里有两个特别顺手的地方:

  • 可以链式调用 AddSubscription

  • 可以为单个主题单独指定 QoS

这已经很接近真实业务系统里的写法了。

十二、WebSocket MQTT:让浏览器也能接进来

如果你的 MQTT 不只是给设备用,还想让 Web 前端直接接进来,那么 WebSocket 版本就非常重要。

在 TouchSocket.Mqtt 里,WebSocket MQTT 的服务端不是直接用 MqttTcpService,而是基于 HttpService 组合出来的。

1. 创建 WebSocket 版 MQTT 服务端

代码块
C#
自动换行
复制代码
using TouchSocket.Core;
using TouchSocket.Http;
using TouchSocket.Mqtt;

var service = new HttpService();

await service.SetupAsync(new TouchSocketConfig()
    .SetListenIPHosts("tcp://127.0.0.1:1883")
    .ConfigureContainer(a =>
    {
        a.AddMqttWebSocketService();
        a.AddConsoleLogger();
    })
    .ConfigurePlugins(a =>
    {
        a.UseMqttWebSocket("/mqtt");
    }));

await service.StartAsync();

Console.WriteLine("WebSocket MQTT 服务端已启动: ws://127.0.0.1:1883/mqtt");
复制成功

这段代码里有两个必须记住的动作:

  1. 容器中注册 AddMqttWebSocketService()

  2. 插件中启用 UseMqttWebSocket("/mqtt")

少任何一个,WebSocket MQTT 都起不来。

2. 创建 WebSocket 版 MQTT 客户端

代码块
C#
自动换行
复制代码
var client = new MqttWebSocketClient();

await client.SetupAsync(new TouchSocketConfig()
    .SetRemoteIPHost("ws://127.0.0.1:1883/mqtt")
    .SetMqttConnectOptions(options =>
    {
        options.ClientId = Guid.NewGuid().ToString("N");
        options.UserName = "admin";
        options.Password = "123456";
        options.ProtocolName = "Mqtt";
        options.Version = MqttProtocolVersion.V500;
        options.KeepAlive = 60;
        options.CleanSession = true;
    }));

await client.ConnectAsync();
复制成功

如果你后续要和浏览器、H5、大屏或者前端控制台集成,这个模式会非常自然。

十三、如何从 WebSocket 服务里拿到 MQTT 服务实例

基于 WebSocket 模式时,HttpService 本身不是 IMqttService,所以如果你想主动广播消息,需要先从容器里解析出 MQTT 服务实例。

示例代码已经给出了标准写法:

代码块
C#
自动换行
复制代码
var mqttService = service.Resolver.Resolve<IMqttWebSocketService>();
var mqttBroker = mqttService.MqttBroker;
复制成功

拿到 mqttBroker 后,就可以像 TCP 服务端那样主动广播消息。

十四、断线重连与保活:这点很实用

示例代码里还有一个很值得单独拿出来讲的点,就是重连插件。

TCP 客户端示例:

代码块
C#
自动换行
复制代码
config.ConfigurePlugins(a =>
{
    a.UseReconnection<MqttTcpClient>(options =>
    {
        options.PollingInterval = TimeSpan.FromSeconds(5);
        options.UseMqttCheckAction(
            activeTimeSpan: TimeSpan.FromSeconds(10),
            pingInterval: TimeSpan.FromSeconds(3));
    });
});
复制成功

WebSocket 客户端示例:

代码块
C#
自动换行
复制代码
config.ConfigurePlugins(a =>
{
    a.UseReconnection<MqttWebSocketClient>(options =>
    {
        options.PollingInterval = TimeSpan.FromSeconds(10);
        options.UseMqttCheckAction();
    });
});
复制成功

这个能力为什么重要?

因为在示例源码里已经明确写了一个很容易被忽略的事实:

KeepAlive 只是把数值传给服务端,客户端本身不会仅凭这个字段自动发送心跳包。

也就是说,如果你希望客户端真正具备“断线重连 + 心跳保活”的能力,就应该把重连插件启起来,而不是只设置一个 KeepAlive = 60 然后安心睡觉。

这是一条非常实用的经验。

十五、连接生命周期插件

除了收消息插件,连接生命周期也可以通过插件来感知。

例如:

代码块
C#
自动换行
复制代码
internal class MqttConnectionPlugin : PluginBase, IMqttConnectingPlugin, IMqttConnectedPlugin
{
    public async Task OnMqttConnecting(IMqttSession client, MqttConnectingEventArgs e)
    {
        Console.WriteLine("Client Connecting");
        await e.InvokeNext();
    }

    public async Task OnMqttConnected(IMqttSession client, MqttConnectedEventArgs e)
    {
        Console.WriteLine("Client Connected");
        await e.InvokeNext();
    }
}
复制成功

如果你要做下面这些功能,这类插件就非常适合:

  • 登录日志

  • 连接审计

  • 统计在线时长

  • 限制重复连接

  • 自定义认证前后的埋点

当前文档和源码中可以看到的常用插件接口包括:

  • IMqttConnectingPlugin

  • IMqttConnectedPlugin

  • IMqttClosingPlugin

  • IMqttClosedPlugin

  • IMqttReceivingPlugin

  • IMqttReceivedPlugin

十六、MQTT 5.0 连接参数,可以先记住这些

如果你想进一步发挥 MQTT 5.0 的能力,MqttConnectOptions 里这些字段值得优先关注:

  • UserProperties 用来带业务元数据

  • AuthenticationMethod 自定义认证方式名

  • AuthenticationData 认证附加数据

  • MaximumPacketSize 限制包大小

  • ReceiveMaximum 限制并发接收 QoS 1/2 消息数量

  • SessionExpiryInterval 会话过期时间

  • TopicAliasMaximum 主题别名能力

如果你的系统走的是更严格的设备认证、复杂的会话控制、或者高并发设备连接,这些配置会逐渐变得重要。

十七、我建议你直接照着跑的 Demo

如果你准备真正上手,而不是只看文章,最推荐从仓库里的这 3 个 demo 开始:

1. examples/Mqtt/MqttConsoleApp

适合先理解最基础的 TCP MQTT 用法:

  • 启动 MqttTcpService

  • 创建 MqttTcpClient

  • 订阅主题

  • 发布消息

  • 配置插件

  • 配置断线重连

2. examples/Mqtt/MqttTopicHandlerConsoleApp

适合理解更贴近业务开发的主题路由模型:

  • UseMqttTopicHandler

  • 精确主题订阅

  • + 单级通配符

  • # 多级通配符

  • 多主题订阅

如果你以后要做“设备消息分发到不同业务处理器”,这个 demo 很值得多看几遍。

3. examples/Mqtt/MqttWebSocketConsoleApp

适合理解 WebSocket MQTT:

  • HttpService

  • AddMqttWebSocketService

  • UseMqttWebSocket("/mqtt")

  • MqttWebSocketClient

  • 从容器解析 IMqttWebSocketService

如果你准备让浏览器直接接 MQTT,这个 demo 基本就是入口样板。

十八、几个很容易踩的坑

最后,把几个容易忽略但真的会影响开发体验的问题单独列出来。

坑 1:KeepAlive 不等于自动心跳

这是最值得提醒的一条。

只设置:

代码块
C#
自动换行
复制代码
options.KeepAlive = 60;
复制成功

并不意味着客户端一定会自动发心跳保活。想要比较完整的保活与断线重连行为,请结合 UseReconnection(...).UseMqttCheckAction(...)。

坑 2:WebSocket MQTT 不是直接 new 一个服务就完事

WebSocket 版必须同时具备:

  • HttpService

  • AddMqttWebSocketService()

  • UseMqttWebSocket("/mqtt")

少一环都不对。

坑 3:主题路由建议尽量早抽象

如果你的主题一开始就不少,建议不要等到几十个主题后再重构,直接上 UseMqttTopicHandler 会省很多事。

坑 4:插件分层要清楚

如果你只想处理业务消息,就优先用 IMqttReceivedPlugin。

如果你要做协议监控、审计、调试,再去用 IMqttReceivingPlugin。

插件职责一混,后面很容易越写越乱。

十九、一个适合放进项目里的最小思路

如果你打算把 TouchSocket.Mqtt 真正用于项目,我建议一开始就按下面这个分层来组织:

服务端层

  • MqttTcpService 或 HttpService + WebSocket MQTT

  • 插件做日志、认证、审计

  • MqttBroker 做主动广播

客户端接入层

  • MqttTcpClient 或 MqttWebSocketClient

  • SetMqttConnectOptions 配身份与版本

  • UseReconnection 配保活与重连

业务消息层

  • 统一约定主题命名

  • 用 UseMqttTopicHandler 管理主题与处理器映射

  • 尽量把消息反序列化、校验、落库封装进独立处理器

这样后面不管你是接 10 台设备,还是接 10000 台设备,代码结构都不至于太散。

结语

如果只用一句话来评价 TouchSocket.Mqtt,我的看法是:

它不是那种只让你“连上就算完事”的 MQTT 包,而是一套比较完整、并且很适合继续往业务里延展的组件方案。

你可以先从最基础的 MqttTcpService + MqttTcpClient 跑起来,再逐步上:

  • 插件化收消息

  • 服务端主动广播

  • 断线重连

  • UseMqttTopicHandler

  • WebSocket MQTT

  • MQTT 5.0 高级配置

这样学习路径是顺的,项目代码也会更稳。

如果你准备马上动手,建议从这条路线开始:

  1. 先跑 MqttConsoleApp

  2. 再跑 MqttTopicHandlerConsoleApp

  3. 最后看 MqttWebSocketConsoleApp

等你把这三个 demo 跑明白,TouchSocket.Mqtt 的核心用法基本就真的进脑子了。