MQTT + Linux + C

分类: MQTT

1. 环境准备 (Linux)

既然是 Linux 环境,我们主要使用命令行 (CLI) 工具。

第一步:安装 .NET SDK

如果你使用的是 Ubuntu/Debian,可以通过以下命令安装(以 .NET 8.0 为例):

Bash

# 更新包列表
sudo apt-get update && sudo apt-get upgrade -y

# 安装 .NET SDK
sudo apt-get install -y dotnet-sdk-8.0

# 验证安装
dotnet --version

(如果是 CentOS 或其他发行版,请参考微软官方文档安装)

第二步:创建项目

在你的工作目录下创建一个控制台应用:

Bash

mkdir MqttLinuxDemo
cd MqttLinuxDemo
dotnet new console

第三步:安装 MQTT 库

使用 NuGet 安装 MQTTnet

Bash

dotnet add package MQTTnet

2. 核心代码开发

我们使用 VS Code 或者直接使用 vim/nano 编辑 Program.cs

场景 A:编写订阅者 (Subscriber)

订阅者通常是一个常驻服务,用来监听设备发来的数据。

Program.cs 修改为以下内容:

C#

using MQTTnet;
using MQTTnet.Client;
using System.Text;

// 1. 创建工厂和客户端
var mqttFactory = new MqttFactory();
using var mqttClient = mqttFactory.CreateMqttClient();

// 2. 配置连接选项 (连接到公共测试服)
var mqttClientOptions = new MqttClientOptionsBuilder()
    .WithTcpServer("broker.emqx.io", 1883)
    .WithClientId("Linux_CSharp_Sub_" + Guid.NewGuid().ToString())
    .Build();

// 3. 设置消息接收回调
mqttClient.ApplicationMessageReceivedAsync += e =>
{
    string payload = Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment);
    string topic = e.ApplicationMessage.Topic;

    // 模拟日志输出
    Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 收到消息 | Topic: {topic}");
    Console.WriteLine($"内容: {payload}");
    Console.WriteLine("--------------------------------------------------");

    return Task.CompletedTask;
};

// 4. 设置断开重连机制 (生产环境必备)
mqttClient.DisconnectedAsync += async e =>
{
    Console.WriteLine("❌ 与 Broker 断开连接,5秒后尝试重连...");
    await Task.Delay(TimeSpan.FromSeconds(5));
    try
    {
        await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
    }
    catch
    {
        Console.WriteLine("重连失败");
    }
};

// 5. 开始连接
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("✅ 已连接到 MQTT Broker");

// 6. 订阅主题
var topicFilter = new MqttTopicFilterBuilder().WithTopic("linux/csharp/test").Build();
await mqttClient.SubscribeAsync(topicFilter);
Console.WriteLine("📡 已订阅主题: linux/csharp/test");

// 7. 阻塞主线程,防止程序退出 (Linux守护进程常用写法)
// 在 Docker 或 Systemd 中,我们需要程序一直运行
await Task.Delay(-1); 

场景 B:编写发布者 (Publisher)

发布者通常是触发式的,比如定时任务或 Web API 收到请求后发送。

新建一个文件 Publisher.cs (或者在另一个项目中):

C#

using MQTTnet;
using MQTTnet.Client;
using System.Text;

var mqttFactory = new MqttFactory();
using var mqttClient = mqttFactory.CreateMqttClient();

var mqttClientOptions = new MqttClientOptionsBuilder()
    .WithTcpServer("broker.emqx.io", 1883)
    .WithClientId("Linux_CSharp_Pub")
    .Build();

await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

// 模拟发送数据
var payload = "Hello from Linux C#";
var message = new MqttApplicationMessageBuilder()
    .WithTopic("linux/csharp/test")
    .WithPayload(payload)
    .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce) // QoS 1
    .WithRetainFlag(false)
    .Build();

await mqttClient.PublishAsync(message, CancellationToken.None);

Console.WriteLine($"🚀 消息已发送: {payload}");

await mqttClient.DisconnectAsync();

3. 在 Linux 上编译与运行

运行订阅者

在终端中执行:

Bash

dotnet run

程序会启动并进入等待状态。

发送测试消息

你可以再开一个终端运行发布者代码,或者直接使用 Linux 命令行工具 mosquitto_pub (如果有安装) 来测试:

Bash

# 如果安装了 mosquitto-clients
mosquitto_pub -h broker.emqx.io -t "linux/csharp/test" -m "Linux Command Line Test"

此时,你的 C# 程序应该会打印出收到的消息。


4. 进阶:如何在 Linux 上部署 (Daemon/Docker)

在 Linux 上,你肯定不希望一直开着终端跑程序。主要有两种方式让它在后台运行。

方法一:使用 Systemd (推荐用于物理机/虚拟机)

  1. 发布程序

Bash

dotnet publish -c Release -o ./publish

  1. 创建服务文件sudo nano /etc/systemd/system/mqtt-worker.service

  2. 写入内容

Ini, TOML

``` [Unit] Description=My C# MQTT Service

[Service] # 指向你的发布目录 WorkingDirectory=/home/user/MqttLinuxDemo/publish # 指向可执行文件 ExecStart=/usr/bin/dotnet /home/user/MqttLinuxDemo/publish/MqttLinuxDemo.dll Restart=always # 重启间隔 RestartSec=10 User=root

[Install] WantedBy=multi-user.target ```

  1. 启动服务

Bash

sudo systemctl daemon-reload sudo systemctl start mqtt-worker sudo systemctl enable mqtt-worker # 开机自启

方法二:使用 Docker (推荐用于容器化部署)

  1. 创建 Dockerfile: 在项目根目录创建名为 Dockerfile 的文件:

Dockerfile

``` # 使用微软官方的运行时镜像 FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base WORKDIR /app

# 使用 SDK 镜像进行构建 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY ["MqttLinuxDemo.csproj", "./"] RUN dotnet restore "MqttLinuxDemo.csproj" COPY . . RUN dotnet build "MqttLinuxDemo.csproj" -c Release -o /app/build

FROM build AS publish RUN dotnet publish "MqttLinuxDemo.csproj" -c Release -o /app/publish

# 最终镜像 FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "MqttLinuxDemo.dll"] ```

  1. 构建并运行

Bash

docker build -t mqtt-csharp-demo . docker run -d --name my-mqtt-app mqtt-csharp-demo


5. 总结与建议

在 Linux 下使用 C# + MQTTnet 开发是非常成熟的方案:

  1. 开发体验:与 Windows 下完全一致(代码不用改)。
  2. 部署:结合 Systemd 或 Docker,非常适合长期运行的 IoT 采集服务。
  3. 性能:.NET 在 Linux 上的性能极高,配合 MQTTnet 的异步处理,单机处理数万并发连接通常不是问题。