Qt 6 + C++17 实现 SFTP 批量部署:工业设备运维工具实战解析

摘要

本文从一个开源项目的真实实现出发,拆解 Qt 6 + C++17 如何实现 SFTP 批量部署 :面向 PLC 设备、Linux 工控机、云服务器的工业设备运维工具 DeviceForge,在 v2.6 版本用 IDeployable 接口把 FTP 与 SFTP 的批量部署做成了同一套部署循环,协议无关、一键切换。

如果你正打算给自研的工业运维工具补 SFTP 部署能力,或者好奇「批量部署」这类功能怎么设计才不把代码写死,这篇实战解析值得读完。


什么是 SFTP 批量部署

先对齐概念。SFTP(SSH File Transfer Protocol)是建立在 SSH 安全通道之上的文件传输协议,与 FTP 的最大区别是全程加密,且复用 SSH 的 22 端口------很多设备默认只开 SSH,不开 FTP 服务。

批量部署指的不是传单个文件,而是:

  • 把一个固件包/程序文件夹递归上传到一台或多台设备
  • 上传前可以清空目标目录(保留目录本身)
  • 传输过程有进度、可取消
  • 多台设备逐台执行,失败隔离------坏一台不影响其余设备

为什么用 SFTP 不用 FTP

这是 v2.6 版本最直接的推动力。v2.5 时工具的 SFTP 只支持「浏览和管理文件」,批量部署必须切回 FTP。但这个边界在实际使用中越来越撑不住:

  • 标准 Linux 服务器、Ubuntu 工控机上,FTP 服务默认没开,SSH 反而是标配
  • 部分支持 SSH 的新设备压根不提供 FTP 服务
  • 云服务器运维场景里,安全组经常只放行 22 端口

单传一个文件还能绕(右键下载再拖上传),批量部署固件就绕不过去了。结论很明确:SFTP 必须成为与 FTP 对等的完整部署通道,而不是「能浏览不能部署」的半成品。

DeviceForge 是什么

DeviceForge(前身 DeployMaster)是一个基于 Qt 6 + C++17 的 Windows 桌面应用,面向工业硬件做「部署 → 测试 → 运维」:

  • FTP/SFTP 批量部署固件
  • Telnet/SSH 批量执行命令
  • Modbus 寄存器读写
  • OPC UA 客户端
  • WebSocket 通信
  • TCP/UDP 网络调试中继

开源项目,GitHub:turnarond/DeviceForge

v2.4 把 FTP 部署从表单改成了双栏文件管理器;v2.5 补完远程文件管理并做了 SylixOS 深度适配;v2.6 把 SFTP 从「单文件传输」变成「完整部署通道」。

Qt 6 怎么实现:IDeployable 接口抽象

这是 v2.6 最核心的技术设计。做法是不往 IProtocolAdapter 塞部署方法 ,而是新增一个可选能力接口 IDeployablesrc/adapter/IDeployable.h):

cpp 复制代码
class IDeployable {
public:
    virtual ~IDeployable() = default;

    // 上传单个文件到远程路径(remotePath 含文件名)
    virtual bool uploadFile(const std::string& localPath, const std::string& remotePath) = 0;

    // 递归上传整个目录(目录本身作为远程子目录创建)
    virtual bool uploadFolder(const std::string& localPath, const std::string& remotePath) = 0;

    // 清空远程目录内容(保留目录本身)
    virtual bool clearRemoteDirectory(const std::string& remotePath) = 0;

    // 进度回调:0-100 整数百分比
    virtual void setProgressCallback(std::function<void(int)> cb) = 0;

    // 取消标志:传输应在每文件/每块前检查并中止
    virtual void setCancelFlag(std::atomic<bool>* flag) = 0;
};

(方法签名以仓库 src/adapter/IDeployable.h 为准)

FtpAdapterSshAdapter 都实现这个接口;部署循环(FtpDeployBackend::startUpload)通过 dynamic_cast 探测------适配器支持部署能力就能进批量部署,与具体协议无关。

这个设计有三个好处:

  1. 映射成本最低 :FTP 已有的方法签名天然对齐(clearRemoteDirectorysetCancelFlag 等),SshAdapter 复用同样语义
  2. 新协议接入零改动 :未来如 SCP,只要实现 IDeployable 就能获得整套批量部署能力,部署循环一行不改
  3. 能力可选 :不支持部署的协议适配器照常存在,dynamic_cast 返回空指针即可优雅降级

递归 mkdir 上传与清空语义

SshAdapter 的三个 SFTP 部署方法,细节都在边界里:

  • sftpUploadFolder :先用 planFolderUpload 递归遍历生成上传计划------目录项在前、文件项在后 ,保证 mkdir 先于文件上传;再逐项执行:目录 mkdir(已存在 EEXIST 忽略,真失败由后续文件上传暴露),文件走 sftpUploadFile(每项前检查取消标志)
  • sftpClearDirectory :清空内容、保留目录本身 ------与 FTP clearRemoteDirectory 语义对齐(直接递归删目录会导致后续上传失败)
  • sftpSetCancelFlag:取消标志挂载,取消后每文件/每块前检查并中止

协议复用:SFTP 走「ssh」注册键

SFTP 部署复用 ssh 协议通道 ------ProtocolRegistry 注册键 "ssh" 的同一 SshAdapter 实现,不新建 sftp 工厂。FtpDeployWidget::currentProtocol() 对 SFTP 返回 "ssh",部署循环直接按该键取适配器。浏览与部署共用同一 SFTP 能力;部署时每设备独立连接(部署循环逐台 create("ssh") 新建适配器实例)。

部署循环与多设备支持

复制代码
Tool = ToolBackend (ServiceTask) + ToolWidget (QWidget)
         ↕ lwmsgq 消息队列解耦
统一 IProtocolAdapter 接口 + ProtocolRegistry 工厂
         ↕ 可选部署能力:IDeployable(dynamic_cast 探测)
FtpAdapter / SshAdapter 均实现 → FtpDeployBackend 部署循环与协议无关

部署循环一次操作覆盖多台设备:逐台执行「连接 → 可选清空 → 上传 → 断开」,进度实时更新、可随时取消,失败设备自动收集跳过、其余设备不受影响。

双栏 UI 与 TC 化体验

v2.6 的双栏文件管理器也完成了 TC 化(Total Commander 风格):统一表格视图、面板顶部路径栏(Enter 跳转)、底部面包屑,快捷键 F2 重命名 / F5 复制到对面 / F6 移动到对面 / Tab 切栏 ;面板间拖拽走部署通道------把文件从左边本地面板拖到右边远程面板即触发上传,拖回即下载,跨面板方向语义清晰(系统文件拖入已移除,仅支持面板间拖拽)。部署目标目录 = 右侧面板当前路径,先导航再部署。

测试验证:11 个测试目标全过

v2.6 新增两个 QtTest 目标,加上既有目标,11 个测试目标全部通过

目标 用例 覆盖
tst_sftp_plan 3 个(plan_singleFile / plan_nestedDir / plan_emptyDir 上传计划生成:单文件、嵌套目录排序、空目录边界
tst_deploy_loop 3 个(deploy_twoDevices_allSuccess / deploy_connectFail_deviceSkipped / deploy_cancelStopsRemaining 部署循环:多设备全成功、连接失败设备跳过、取消中止剩余

(另有 tst_remote_modeltst_themetst_file_source 等既有目标回归全过,CI 在 GitHub Actions 上跑 CMake + CTest)

诚实的限制

  • SCP 未做 (v2.7 候选):IDeployable 接口已就位,SCP 只需实现接口 + 注册协议键即可获得整套部署能力
  • 无断点续传:传输中断需重新部署
  • 密钥认证待后续:SFTP 部署目前用账号密码认证(与浏览路径一致),SSH 私钥登录未接通

总结

v2.6 不是新功能堆叠,而是把最后一个传输缺口补上:

  1. SFTP 批量部署与 FTP 完全对等------同一双栏 UI 一键切换(FTP/SFTP 协议下拉),不用再为不同设备切换工具
  2. IDeployable 接口抽象------部署能力与协议解耦,SCP 等新协议接入成本降到最低
  3. 递归 mkdir 上传 + 清空保留目录 + 取消------语义与 FTP 对齐,行为可预期

配套的还有暗/亮双主题(设置中切换)、状态栏快捷键提示、部署方向指示等体验细节。

如果你也经常给 PLC 设备、Linux 工控机、云服务器批量传固件------FTP 和 SFTP 混着用的场景,这一版值得试试。

GitHub 开源地址turnarond/DeviceForge(欢迎 star / issue / PR)


作者简介

turnarond,工业软件开发者,专注设备运维工具链(Qt / C++ / 工业协议)。持续分享 DeployMaster → DeviceForge 从单体架构到服务核 + Qt 壳双层架构的实战改造过程。关注本专栏,下一篇拆解 IFileSource 文件源抽象与双栏面板模块化。

作者:turnarond | 2026-08-13

相关推荐
雨辰AI2 小时前
RAG 知识库搭建:基于人大金仓构建信创运维问答机器人|全栈国产化落地完整版
运维·ai·机器人·ai编程
-今昭-2 小时前
Ansible
linux·运维·ansible
星野川崎2062 小时前
电商多店运维:云机长期挂机频繁掉线、账号无故风控原因剖析与解决方案
大数据·运维·云计算·电商
码匠许师傅2 小时前
【C++ 面试真题】聊聊 C++ 的多继承与虚继承
开发语言·c++·面试
我不是疯子是傻子3 小时前
Qt CAN通信周期发送抖动?实测定时器精度校准与时间戳补偿方案
开发语言·数据库·qt
有点。4 小时前
C++认识数
开发语言·c++
IT邦德4 小时前
Dify1.6基于ubuntu系统的部署实战
linux·运维·ubuntu
2023自学中4 小时前
Qt 简易聊天室(第二篇),单线程 改为 多线程,方便后续增加文件传输功能
c++·qt
蓝速科技5 小时前
蓝速科技会议电子门牌规模化部署与运维成本实测
运维·科技