基于 Rust Tauri 的桌面 MQTT 调试客户端项目开源地址https://gitcode.com/qq8864/atomMqtt1. 概述AtomMQTT Client 是一个跨平台桌面 MQTT 调试工具使用Tauri v1框架构建。其核心架构为┌─────────────────────────────────────┐ │ Web 前端 │ │ HTML CSS (Tokyo Night) JS │ │ ───────── Tauri IPC ──────────▶ │ ├─────────────────────────────────────┤ │ Rust 后端 │ │ rumqttc MQTT 客户端 │ │ Tokio 异步事件循环 │ │ Tauri 命令处理层 │ └─────────────────────────────────────┘技术栈层次技术版本桌面框架Tauri1.6后端语言Rust2021 editionMQTT 协议rumqttc0.24异步运行时Tokio1.36 (full)序列化serde serde_json1.0前端原生 HTML/CSS/JS—项目开源地址https://gitcode.com/qq8864/atomMqtt2. Rust 后端实现2.1 数据模型MqttMessage — 消息结构#[derive(Debug, Clone, Serialize)]pubstructMqttMessage{pubtopic:String,// 消息主题pubpayload:String,// UTF-8 载荷文本pubpayload_hex:String,// Hex 编码载荷用于二进制数据查看pubqos:u8,// 服务质量 (0/1/2)pubretain:bool,// 保留消息标志pubtimestamp:String,// 接收时间毫秒精度pubpacket_id:Optionu16,// MQTT 包 ID}每条接收到的消息会同时保存UTF-8 文本和Hex 编码两种形式的载荷前端可在 UI 中切换显示。ConnectionStatus — 连接状态pubstructConnectionStatus{pubconnected:bool,pubhost:String,pubport:u16,pubclient_id:String,pubconnected_at:OptionString,}SubscriptionInfo — 订阅信息pubstructSubscriptionInfo{pubtopic_filter:String,pubqos:u8,}2.2 全局状态管理使用 Tauri 的State管理模式通过AppState结构体管理所有运行时状态pubstructAppState{pubclient:MutexOptionAsyncClient,// MQTT 客户端句柄pubmessages:ArcMutexVecMqttMessage,// 消息缓冲区pubconnected:ArcAtomicBool,// 连接标志pubhost:MutexString,pubport:Mutexu16,pubclient_id:MutexString,pubconnected_at:ArcMutexOptionString,pubsubscriptions:MutexVecSubscriptionInfo,}设计要点AsyncClient用MutexOption...包装支持连接断开和重建messages和connected使用Arc跨线程共享前端轮询线程与 MQTT 事件循环线程AtomicBool用于connected标志——无锁读取性能最优消息缓冲区上限10,000 条避免内存泄漏2.3 MQTT 连接与管理连接流程使用rumqttc库的AsyncClientAPIasyncfnconnect(state:State_,AppState,host:String,port:u16,client_id:String,username:OptionString,password:OptionString,clean_session:Optionbool,)-ResultString,String步骤断开旧连接如果已有连接先优雅断开创建 MQTT 选项设置 Keep-Alive30秒、Clean Session、可选的用户名密码认证创建客户端AsyncClient::new(options, 100)— 100 为消息队列容量存储客户端句柄保存到AppState.client供 publish/subscribe 使用启动事件循环tokio::spawn一个异步任务持续处理 MQTT 事件事件循环处理在后台线程中循环调用eventloop.poll().await事件类型处理逻辑ConnAck连接成功 → 设置connected true记录连接时间Publish收到消息 → 生成MqttMessage并存入缓冲区Disconnect服务端断开 → 设置connected false退出循环PingRespKeep-Alive 响应 → 忽略错误记录日志等待 3 秒后重试容忍瞬态网络错误2.4 Tauri 命令层共注册8 个 Tauri 命令前端通过window.__TAURI__.tauri.invoke()调用命令功能参数返回值connect连接 Brokerhost, port, client_id, username?, password?, clean_session?连接成功信息disconnect断开连接无()publish发布消息topic, payload, qos, retain()subscribe订阅主题topic_filter, qos()unsubscribe取消订阅topic_filter()get_messages获取消息列表无VecMqttMessageclear_messages清空消息无()get_connection_status获取连接状态无ConnectionStatusget_subscriptions获取订阅列表无VecSubscriptionInfo每个命令的核心模式#[tauri::command]asyncfncommand_name(state:State_,AppState,...args)-Result...,String{// 1. 从 state 获取客户端句柄加锁letclientstate.client.lock()?.as_ref().ok_or(Not connected)?.clone();// 2. 执行操作client.do_something(...).await.map_err(|e|e.to_string())?;// 3. 更新状态Ok(...)}Result的Err(String)会自动传递给前端 JavaScript 的catch块。3. 前端实现3.1 HTML 布局采用经典的左-右两栏布局┌─ Title Bar ──────────────────────────────────┐ │ ◈ AtomMQTT Client ● 在线 v1.0.0 │ ├──────────┬────────────────────────────────────┤ │ Sidebar │ Tabs: [发布] [订阅] [消息日志] │ │ │ │ │ 连接设置 │ ── 发布 Tab ── │ │ Broker │ 主题: [__________] │ │ 客户端ID │ 载荷: [__________] │ │ 用户名 │ QoS: [v] 保留: [x] [发布] │ │ 密码 │ │ │ [连接] │ ── 订阅 Tab ── │ │ [断开] │ 过滤器: [___] QoS: [v] [订阅] │ │ │ 活跃订阅列表 │ │ 状态: 在线│ │ │ 时间: ...│ ── 消息日志 Tab ── │ │ │ [自动滚动] [Hex] [清空] │ │ │ 2026-05-28 12:34:56.789 │ │ │ test/topic │ │ │ hello world │ ├──────────┴────────────────────────────────────┤ │ Status Bar: ● 已连接 就绪 │ └───────────────────────────────────────────────┘3.2 样式系统 (Tokyo Night 主题)使用 CSS 自定义属性定义配色方案灵感来自 Tokyo Night 主题:root{--bg-primary:#1a1b26;--bg-secondary:#24253a;--bg-tertiary:#2d2e42;--text-primary:#e2e3eb;--accent:#7aa2f7;--success:#9ece6a;--danger:#f7768e;}主题特性深色背景 高对比度文字适合长时间调试使用等宽字体栈Cascadia Code → Fira Code → JetBrains Mono → Consolas平滑动画和圆角设计响应式布局最小宽度 680px3.3 JavaScript 逻辑通信机制前端通过window.__TAURI__.tauri.invoke()与 Rust 后端通信const{invoke}window.__TAURI__.tauri;// 调用 Rust 命令constresultawaitinvoke(connect,{host:127.0.0.1,port:1883,clientId:my-client,// ...});状态轮询采用轮询模式而非 WebSocket/SSE获取运行状态和消息functionstartPolling(){pollTimersetInterval(pollStatus,1000);// 每秒轮询}asyncfunctionpollStatus(){// 1. 获取连接状态conststatusawaitinvoke(get_connection_status);setConnected(status.connected);// 2. 获取新消息constmsgsawaitinvoke(get_messages);updateLog(msgs);}设计原因Tauri v1 的 invoke 调用延迟极低1ms轮询 1 秒间隔不会产生任何可感知的性能开销且实现简单可靠。对于 MQTT 调试场景消息延迟 1 秒以内完全可接受。消息日志增量更新letprevMsgCount0;functionupdateLog(msgs){if(msgs.lengthprevMsgCount)return;// 无新消息跳过conststartIdxprevMsgCount;constnewMsgsmsgs.slice(startIdx);// 仅处理新增消息for(constmsgofnewMsgs){constentrydocument.createElement(div);// 构建 DOM 元素logContainer.appendChild(entry);}prevMsgCountmsgs.length;}快捷键支持快捷键功能CtrlEnter快速发布publish 按钮Escape取消当前输入框焦点消息条双击切换 Hex/UTF-8 视图4. 构建与部署4.1 构建流程推荐使用项目自带的构建脚本$ build.bat脚本执行步骤cargo build --release— 编译 Rust 后端 Tauri 打包前端静态资源fix_pe.cmd— 自动修复 PE 头仅 rust-lld 链接器需要见 4.4 节复制target/release/tauri-mqtt-client.exe→dist/AtomMQTT-Client.exeTauri 在编译过程中会自动编译 Rust 后端 →tauri-mqtt-client.exe读取tauri.conf.json中的distDir: public→ 将public/目录打包为静态资源嵌入 Windows 资源图标、版本信息输出最终的target/release/tauri-mqtt-client.exe4.2 Tauri 配置 (tauri.conf.json)关键配置项{build:{distDir:public,// 前端静态文件目录devPath:public// 开发模式下也直接使用静态文件},package:{productName:AtomMQTT Client,version:1.0.0},tauri:{allowlist:{shell:{open:true}// 允许打开外部链接},windows:[{title:AtomMQTT Client,width:1080,height:800,minWidth:680,minHeight:500,center:true}]}}4.3 Windows 子系统设置 — 消除 DOS 窗口默认 Rust 编译 Windows 程序时使用控制台子系统Subsystem3导致程序启动时会同时弹出一个 DOS 控制台窗口。对于桌面 GUI 应用需要改为GUI 子系统Subsystem2。在main.rs顶部添加#![windows_subsystem windows]这行代码告诉链接器这是一个 Windows GUI 应用无需分配控制台。Tauri 文档也推荐所有正式发布的桌面应用加上此属性。4.4 PE 头损坏修复 — 解决此版本与 Windows 不兼容问题现象在 Windows 上使用rust-lldLLVM LLD 链接器Rust 工具链自带替代 MSVClink.exe链接时生成的.exe文件的DOS 头中的e_lfanew字段被写为 0。该字段是 PE 文件格式的入口指针——它指向真正的 PE 签名PE\0\0在文件中的偏移量。一旦为零Windows 加载器无法定位 PE 头就会报告“此版本与正在运行的 Windows 版本不兼容”PE 文件结构示意┌─ DOS Header (64 bytes) ──────────────────┐ │ ... │ │ e_lfanew 0x78 ← 指向 PE 签名偏移 │ │ ... │ ├─ DOS Stub ────────────────────────────────┤ │ This program cannot be run in DOS mode │ ├─ PE Signature ────────────────────────────┤ │ PE\0\0 ← Windows 从此处加载 │ ├─ COFF / Optional Headers ─────────────────┤ │ ... │ └───────────────────────────────────────────┘根本原因rust-lld 在生成 PE 文件时会写入错误的值到e_lfanew字段偏移 0x3C 处4 字节。这在rust-lld的多个版本中均有出现是 LLVM LLD 的一个已知问题。解决方案运行时修复在build.rsTauri 构建脚本中添加一个PE 头修复步骤编译完成后扫描生成的.exe文件找到PE\0\0签名在文件中的实际偏移量然后将正确的值写回e_lfanew字段。build.rs中生成修复脚本的核心逻辑fnmain(){println!(cargo:rerun-if-changedbuild.rs);// 读取编译后的 exe 文件letexe_pathstd::env::current_dir().unwrap().join(target\\release\\tauri-mqtt-client.exe);// 生成修复脚本 fix_pe.cmdletscriptformat!(powershell -Command \$b[System.IO.File]::ReadAllBytes({}); ... \,exe_path.display());std::fs::write(fix_pe.cmd,script).unwrap();}修复脚本运行后Windows 加载器能够正确读取 PE 头应用正常启动。构建修复前后对比指标修复前修复后启动是否弹 DOS 窗口❌ 弹出控制台窗口✅ 无窗口是否可运行❌ “版本不兼容” 错误✅ 正常启动构建工具cargo buildbuild.bat额外步骤无build.rs 生成 → fix_pe.cmd 执行5. 文件结构tools/tauri-mqtt-client/ ├── Cargo.toml # Rust 依赖配置 ├── build.rs # Tauri 构建脚本含 PE 头修复代码生成 ├── build.bat # 一键构建脚本编译 → 修复 PE → 复制到 dist ├── fix_pe.cmd # PE 头修复脚本由 build.rs 自动生成 ├── tauri.conf.json # Tauri 应用配置 ├── .cargo/ │ └── config.toml # Rust 链接器配置rust-lld ├── icons/ │ ├── icon.ico # Windows 程序图标 │ └── icon.png # PNG 图标 ├── public/ # 前端静态文件distDir │ ├── index.html # 主页面 │ ├── styles.css # 样式表640 行 │ └── script.js # 前端逻辑353 行 ├── src/ │ └── main.rs # Rust 后端323 行 ├── dist/ # 构建产出 │ └── AtomMQTT-Client.exe # 可执行文件 └── install.bat # Windows 安装脚本6. 与同等工具的比较特性AtomMQTT ClientMQTTX (Electron)mosquitto_sub (CLI)二进制体积~7 MB~120 MB~500 KB但不含 GUI内存占用~40 MB~200 MB—启动速度500ms~3s瞬发GUI 框架Tauri (系统 WebView)Electron (Chromium)无QoS 支持0/1/20/1/20/1/2Hex 视图✅✅❌主题Tokyo Night 深色可切换无AtomMQTT Client 的核心优势在于极低的资源占用和快速的启动速度利用了操作系统内置的 WebView2 Runtime无需捆绑 Chromium。7. 总结AtomMQTT Client 是一个轻量、高效、美观的 MQTT 桌面调试工具Rust 后端通过rumqttc实现完整的 MQTT 3.1.1 协议支持Tauri 框架提供原生桌面体验无需 Electron 的臃肿原生前端HTML/CSS/JS零依赖启动即用Tokyo Night 深色主题适合开发者长时间使用双视图消息日志UTF-8 / Hex方便调试二进制协议整个项目约1,300 行代码Rust 323 行 JS 353 行 CSS 640 行体现了 Rust Tauri 栈构建桌面应用的简洁与高效。
Rust+ Tauri实现漂亮小巧的Mqtt客户端工具--AtomMQTT Client 实现详解
发布时间:2026/5/29 1:12:25
基于 Rust Tauri 的桌面 MQTT 调试客户端项目开源地址https://gitcode.com/qq8864/atomMqtt1. 概述AtomMQTT Client 是一个跨平台桌面 MQTT 调试工具使用Tauri v1框架构建。其核心架构为┌─────────────────────────────────────┐ │ Web 前端 │ │ HTML CSS (Tokyo Night) JS │ │ ───────── Tauri IPC ──────────▶ │ ├─────────────────────────────────────┤ │ Rust 后端 │ │ rumqttc MQTT 客户端 │ │ Tokio 异步事件循环 │ │ Tauri 命令处理层 │ └─────────────────────────────────────┘技术栈层次技术版本桌面框架Tauri1.6后端语言Rust2021 editionMQTT 协议rumqttc0.24异步运行时Tokio1.36 (full)序列化serde serde_json1.0前端原生 HTML/CSS/JS—项目开源地址https://gitcode.com/qq8864/atomMqtt2. Rust 后端实现2.1 数据模型MqttMessage — 消息结构#[derive(Debug, Clone, Serialize)]pubstructMqttMessage{pubtopic:String,// 消息主题pubpayload:String,// UTF-8 载荷文本pubpayload_hex:String,// Hex 编码载荷用于二进制数据查看pubqos:u8,// 服务质量 (0/1/2)pubretain:bool,// 保留消息标志pubtimestamp:String,// 接收时间毫秒精度pubpacket_id:Optionu16,// MQTT 包 ID}每条接收到的消息会同时保存UTF-8 文本和Hex 编码两种形式的载荷前端可在 UI 中切换显示。ConnectionStatus — 连接状态pubstructConnectionStatus{pubconnected:bool,pubhost:String,pubport:u16,pubclient_id:String,pubconnected_at:OptionString,}SubscriptionInfo — 订阅信息pubstructSubscriptionInfo{pubtopic_filter:String,pubqos:u8,}2.2 全局状态管理使用 Tauri 的State管理模式通过AppState结构体管理所有运行时状态pubstructAppState{pubclient:MutexOptionAsyncClient,// MQTT 客户端句柄pubmessages:ArcMutexVecMqttMessage,// 消息缓冲区pubconnected:ArcAtomicBool,// 连接标志pubhost:MutexString,pubport:Mutexu16,pubclient_id:MutexString,pubconnected_at:ArcMutexOptionString,pubsubscriptions:MutexVecSubscriptionInfo,}设计要点AsyncClient用MutexOption...包装支持连接断开和重建messages和connected使用Arc跨线程共享前端轮询线程与 MQTT 事件循环线程AtomicBool用于connected标志——无锁读取性能最优消息缓冲区上限10,000 条避免内存泄漏2.3 MQTT 连接与管理连接流程使用rumqttc库的AsyncClientAPIasyncfnconnect(state:State_,AppState,host:String,port:u16,client_id:String,username:OptionString,password:OptionString,clean_session:Optionbool,)-ResultString,String步骤断开旧连接如果已有连接先优雅断开创建 MQTT 选项设置 Keep-Alive30秒、Clean Session、可选的用户名密码认证创建客户端AsyncClient::new(options, 100)— 100 为消息队列容量存储客户端句柄保存到AppState.client供 publish/subscribe 使用启动事件循环tokio::spawn一个异步任务持续处理 MQTT 事件事件循环处理在后台线程中循环调用eventloop.poll().await事件类型处理逻辑ConnAck连接成功 → 设置connected true记录连接时间Publish收到消息 → 生成MqttMessage并存入缓冲区Disconnect服务端断开 → 设置connected false退出循环PingRespKeep-Alive 响应 → 忽略错误记录日志等待 3 秒后重试容忍瞬态网络错误2.4 Tauri 命令层共注册8 个 Tauri 命令前端通过window.__TAURI__.tauri.invoke()调用命令功能参数返回值connect连接 Brokerhost, port, client_id, username?, password?, clean_session?连接成功信息disconnect断开连接无()publish发布消息topic, payload, qos, retain()subscribe订阅主题topic_filter, qos()unsubscribe取消订阅topic_filter()get_messages获取消息列表无VecMqttMessageclear_messages清空消息无()get_connection_status获取连接状态无ConnectionStatusget_subscriptions获取订阅列表无VecSubscriptionInfo每个命令的核心模式#[tauri::command]asyncfncommand_name(state:State_,AppState,...args)-Result...,String{// 1. 从 state 获取客户端句柄加锁letclientstate.client.lock()?.as_ref().ok_or(Not connected)?.clone();// 2. 执行操作client.do_something(...).await.map_err(|e|e.to_string())?;// 3. 更新状态Ok(...)}Result的Err(String)会自动传递给前端 JavaScript 的catch块。3. 前端实现3.1 HTML 布局采用经典的左-右两栏布局┌─ Title Bar ──────────────────────────────────┐ │ ◈ AtomMQTT Client ● 在线 v1.0.0 │ ├──────────┬────────────────────────────────────┤ │ Sidebar │ Tabs: [发布] [订阅] [消息日志] │ │ │ │ │ 连接设置 │ ── 发布 Tab ── │ │ Broker │ 主题: [__________] │ │ 客户端ID │ 载荷: [__________] │ │ 用户名 │ QoS: [v] 保留: [x] [发布] │ │ 密码 │ │ │ [连接] │ ── 订阅 Tab ── │ │ [断开] │ 过滤器: [___] QoS: [v] [订阅] │ │ │ 活跃订阅列表 │ │ 状态: 在线│ │ │ 时间: ...│ ── 消息日志 Tab ── │ │ │ [自动滚动] [Hex] [清空] │ │ │ 2026-05-28 12:34:56.789 │ │ │ test/topic │ │ │ hello world │ ├──────────┴────────────────────────────────────┤ │ Status Bar: ● 已连接 就绪 │ └───────────────────────────────────────────────┘3.2 样式系统 (Tokyo Night 主题)使用 CSS 自定义属性定义配色方案灵感来自 Tokyo Night 主题:root{--bg-primary:#1a1b26;--bg-secondary:#24253a;--bg-tertiary:#2d2e42;--text-primary:#e2e3eb;--accent:#7aa2f7;--success:#9ece6a;--danger:#f7768e;}主题特性深色背景 高对比度文字适合长时间调试使用等宽字体栈Cascadia Code → Fira Code → JetBrains Mono → Consolas平滑动画和圆角设计响应式布局最小宽度 680px3.3 JavaScript 逻辑通信机制前端通过window.__TAURI__.tauri.invoke()与 Rust 后端通信const{invoke}window.__TAURI__.tauri;// 调用 Rust 命令constresultawaitinvoke(connect,{host:127.0.0.1,port:1883,clientId:my-client,// ...});状态轮询采用轮询模式而非 WebSocket/SSE获取运行状态和消息functionstartPolling(){pollTimersetInterval(pollStatus,1000);// 每秒轮询}asyncfunctionpollStatus(){// 1. 获取连接状态conststatusawaitinvoke(get_connection_status);setConnected(status.connected);// 2. 获取新消息constmsgsawaitinvoke(get_messages);updateLog(msgs);}设计原因Tauri v1 的 invoke 调用延迟极低1ms轮询 1 秒间隔不会产生任何可感知的性能开销且实现简单可靠。对于 MQTT 调试场景消息延迟 1 秒以内完全可接受。消息日志增量更新letprevMsgCount0;functionupdateLog(msgs){if(msgs.lengthprevMsgCount)return;// 无新消息跳过conststartIdxprevMsgCount;constnewMsgsmsgs.slice(startIdx);// 仅处理新增消息for(constmsgofnewMsgs){constentrydocument.createElement(div);// 构建 DOM 元素logContainer.appendChild(entry);}prevMsgCountmsgs.length;}快捷键支持快捷键功能CtrlEnter快速发布publish 按钮Escape取消当前输入框焦点消息条双击切换 Hex/UTF-8 视图4. 构建与部署4.1 构建流程推荐使用项目自带的构建脚本$ build.bat脚本执行步骤cargo build --release— 编译 Rust 后端 Tauri 打包前端静态资源fix_pe.cmd— 自动修复 PE 头仅 rust-lld 链接器需要见 4.4 节复制target/release/tauri-mqtt-client.exe→dist/AtomMQTT-Client.exeTauri 在编译过程中会自动编译 Rust 后端 →tauri-mqtt-client.exe读取tauri.conf.json中的distDir: public→ 将public/目录打包为静态资源嵌入 Windows 资源图标、版本信息输出最终的target/release/tauri-mqtt-client.exe4.2 Tauri 配置 (tauri.conf.json)关键配置项{build:{distDir:public,// 前端静态文件目录devPath:public// 开发模式下也直接使用静态文件},package:{productName:AtomMQTT Client,version:1.0.0},tauri:{allowlist:{shell:{open:true}// 允许打开外部链接},windows:[{title:AtomMQTT Client,width:1080,height:800,minWidth:680,minHeight:500,center:true}]}}4.3 Windows 子系统设置 — 消除 DOS 窗口默认 Rust 编译 Windows 程序时使用控制台子系统Subsystem3导致程序启动时会同时弹出一个 DOS 控制台窗口。对于桌面 GUI 应用需要改为GUI 子系统Subsystem2。在main.rs顶部添加#![windows_subsystem windows]这行代码告诉链接器这是一个 Windows GUI 应用无需分配控制台。Tauri 文档也推荐所有正式发布的桌面应用加上此属性。4.4 PE 头损坏修复 — 解决此版本与 Windows 不兼容问题现象在 Windows 上使用rust-lldLLVM LLD 链接器Rust 工具链自带替代 MSVClink.exe链接时生成的.exe文件的DOS 头中的e_lfanew字段被写为 0。该字段是 PE 文件格式的入口指针——它指向真正的 PE 签名PE\0\0在文件中的偏移量。一旦为零Windows 加载器无法定位 PE 头就会报告“此版本与正在运行的 Windows 版本不兼容”PE 文件结构示意┌─ DOS Header (64 bytes) ──────────────────┐ │ ... │ │ e_lfanew 0x78 ← 指向 PE 签名偏移 │ │ ... │ ├─ DOS Stub ────────────────────────────────┤ │ This program cannot be run in DOS mode │ ├─ PE Signature ────────────────────────────┤ │ PE\0\0 ← Windows 从此处加载 │ ├─ COFF / Optional Headers ─────────────────┤ │ ... │ └───────────────────────────────────────────┘根本原因rust-lld 在生成 PE 文件时会写入错误的值到e_lfanew字段偏移 0x3C 处4 字节。这在rust-lld的多个版本中均有出现是 LLVM LLD 的一个已知问题。解决方案运行时修复在build.rsTauri 构建脚本中添加一个PE 头修复步骤编译完成后扫描生成的.exe文件找到PE\0\0签名在文件中的实际偏移量然后将正确的值写回e_lfanew字段。build.rs中生成修复脚本的核心逻辑fnmain(){println!(cargo:rerun-if-changedbuild.rs);// 读取编译后的 exe 文件letexe_pathstd::env::current_dir().unwrap().join(target\\release\\tauri-mqtt-client.exe);// 生成修复脚本 fix_pe.cmdletscriptformat!(powershell -Command \$b[System.IO.File]::ReadAllBytes({}); ... \,exe_path.display());std::fs::write(fix_pe.cmd,script).unwrap();}修复脚本运行后Windows 加载器能够正确读取 PE 头应用正常启动。构建修复前后对比指标修复前修复后启动是否弹 DOS 窗口❌ 弹出控制台窗口✅ 无窗口是否可运行❌ “版本不兼容” 错误✅ 正常启动构建工具cargo buildbuild.bat额外步骤无build.rs 生成 → fix_pe.cmd 执行5. 文件结构tools/tauri-mqtt-client/ ├── Cargo.toml # Rust 依赖配置 ├── build.rs # Tauri 构建脚本含 PE 头修复代码生成 ├── build.bat # 一键构建脚本编译 → 修复 PE → 复制到 dist ├── fix_pe.cmd # PE 头修复脚本由 build.rs 自动生成 ├── tauri.conf.json # Tauri 应用配置 ├── .cargo/ │ └── config.toml # Rust 链接器配置rust-lld ├── icons/ │ ├── icon.ico # Windows 程序图标 │ └── icon.png # PNG 图标 ├── public/ # 前端静态文件distDir │ ├── index.html # 主页面 │ ├── styles.css # 样式表640 行 │ └── script.js # 前端逻辑353 行 ├── src/ │ └── main.rs # Rust 后端323 行 ├── dist/ # 构建产出 │ └── AtomMQTT-Client.exe # 可执行文件 └── install.bat # Windows 安装脚本6. 与同等工具的比较特性AtomMQTT ClientMQTTX (Electron)mosquitto_sub (CLI)二进制体积~7 MB~120 MB~500 KB但不含 GUI内存占用~40 MB~200 MB—启动速度500ms~3s瞬发GUI 框架Tauri (系统 WebView)Electron (Chromium)无QoS 支持0/1/20/1/20/1/2Hex 视图✅✅❌主题Tokyo Night 深色可切换无AtomMQTT Client 的核心优势在于极低的资源占用和快速的启动速度利用了操作系统内置的 WebView2 Runtime无需捆绑 Chromium。7. 总结AtomMQTT Client 是一个轻量、高效、美观的 MQTT 桌面调试工具Rust 后端通过rumqttc实现完整的 MQTT 3.1.1 协议支持Tauri 框架提供原生桌面体验无需 Electron 的臃肿原生前端HTML/CSS/JS零依赖启动即用Tokyo Night 深色主题适合开发者长时间使用双视图消息日志UTF-8 / Hex方便调试二进制协议整个项目约1,300 行代码Rust 323 行 JS 353 行 CSS 640 行体现了 Rust Tauri 栈构建桌面应用的简洁与高效。