前言:RemoteCtrl 是一个基于 C++20 协程的远程控制软件,支持文件管理、远程桌面监控、远程终端控制等功能。客户端使用 Qt5 GUI,服务端使用 coronet 异步 I/O 协程库。
RemoteCtrl
RemoteCtrl- Github||Gitee
功能特色
- 文件管理:远程浏览文件目录树,支持文件下载(断点续传)、删除、远程打开
- 远程桌面监控:实时屏幕共享(30 FPS),鼠标事件转发,支持锁屏/解锁
- 远程终端控制:Lock/Unlock 远程机器的键盘鼠标
- 守护进程模式:支持开机自启、后台静默运行(
-DBACKGROUND=ON)
- 跨平台通信:自定义二进制协议,CRC32C 校验,支持大文件传输
- 告别编码问题:全链路 UTF-8,中文文件名无乱码
架构设计
1 2 3 4 5 6
| ┌────────────────────────────┐ TCP ┌─────────────────────────┐ │ RemoteCtrlApp (Client) │ ◄─────────────► │ RemoteCtrlServer │ │ Qt5 Widgets · C++20 │ 自定义二进制协议 │ C++20 · coronet 协程 │ │ coronet 协程(独立I/O线程)│ │ Qt5::Core (文件操作) │ │ Windows 10+ (x64) │ │ Windows / Linux │ └────────────────────────────┘ └─────────────────────────┘
|
客户端线程模型
1 2 3 4 5 6 7
| ┌──────────────────────────┐ mutex 队列 ┌───────────────────────┐ │ Qt 主线程 (UI 事件循环) │ ◄──────────────► │ coronet I/O 线程 │ │ MainWindow │ Packet in/out │ writerLoop (发送) │ │ MonitorWindow │ │ readerLoop (接收) │ │ DownloadDialog │ │ io_context 事件循环 │ │ 每 50ms 轮询接收队列 │ │ │ └──────────────────────────┘ └───────────────────────┘
|
服务端线程模型
1 2 3 4 5 6 7 8 9 10 11
| ┌──────────────────────────────────────────────┐ │ io_context (单线程事件循环) │ │ │ │ ┌──────────────┐ ┌───────────────────┐ │ │ │ acceptLoop │ │ SessionHandler │ │ │ │ (接收连接) │ │ (每个客户端) │ │ │ └──────────────┘ └───────────────────┘ │ │ ├─ readLoop (接收) │ │ ├─ 命令分发 │ │ └─ screenStream (截图) │ └──────────────────────────────────────────────┘
|
技术选型
| 组件 |
技术 |
说明 |
| 异步 I/O |
coronet |
C++20 协程库,跨平台 IOCP/epoll/io_uring,零虚表开销 |
| GUI |
Qt 5.12 Widgets |
稳定的桌面 UI 框架 |
| 构建系统 |
CMake 3.20+ |
支持 MSVC,自动管理依赖 |
| 编译器 |
MSVC 2022 |
C++20 标准 |
| 文件操作 |
Qt5::Core (QFile/QDir) |
统一 UTF-8 编码 |
| JPEG 编码 |
WIC (Windows Imaging Component) |
硬件加速图像编码 |
| 日志 |
自研轮转文件日志 |
写入 %%TEMP%%/RemoteCtrlServer/,10MB 轮转 |
核心代码逻辑
通信协议
自定义二进制协议,所有操作通过同一套包格式完成:
1 2 3 4 5
| ┌─────────────────────────────────────────────────────────┐ │ Header (16B) │ Command (4B) │ Payload Length (8B) │ CRC32C (4B) │ │ magic=0x524D │ cmd ID │ payload size │ 校验和 │ │ 5443 ("RMTC") │ │ │ │ └─────────────────────────────────────────────────────────┘
|
- 校验:CRC32C(SSE4.2 硬件加速,32-bit 兼容回退)
- 字符串:长度前缀
[uint16_t len][UTF-8 data]
- 命令集:Ping/Pong、ListDrives、ListDir、DeleteFile、DownloadReq/Start/Resp/Complete/Cancel、OpenFile、ScreenFrame、MouseEvent、LockScreen 等
数据通信核心流程
连接与文件浏览
1 2 3 4 5 6 7
| Client Server │ │ │──── TCP Connect ────────► │ │──── LIST_DRIVES ────────► │ │◄──── DRIVE_LIST ───────── │ ← 枚举磁盘 (GetLogicalDriveStrings) │──── LIST_DIR ("C:/") ───► │ │◄──── DIR_ENTRIES ──────── │ ← 目录/文件分离,子目录加树,文件显示在右侧
|
文件下载(断点续传)
1 2 3 4 5 6 7 8 9 10 11 12
| Client Server │ │ │──── DOWNLOAD_REQ ───────► │ path + offset │◄──── DOWNLOAD_START ───── │ file_size + name │◄──── DOWNLOAD_RESP ────── │ 64KB 数据块 × N │◄──── DOWNLOAD_COMPLETE ── │ 传输完成 │ │ │ (断线重连后) │ │──── DOWNLOAD_REQ ───────► │ offset = 已接收字节数 │◄──── DOWNLOAD_START ───── │ file_size + name │◄──── DOWNLOAD_RESP ────── │ 从偏移处继续 │◄──── DOWNLOAD_COMPLETE ── │
|
屏幕共享
1 2 3 4 5 6 7 8 9
| Client Server │ │ │──── SCREEN_START ───────► │ │◄──── SCREEN_FRAME ─────── │ JPEG 编码的桌面截图, ~20 FPS │◄──── SCREEN_FRAME ─────── │ 持续推送 │──── SCREEN_STOP ────────► │ │ │ │ (鼠标事件转发) │ │──── MOUSE_EVENT ────────► │ SendInput 模拟鼠标
|
服务端截图流水线
1
| GDI BitBlt → 32-bit BGRA → BGR(24-bit) 转换 → WIC JPEG 编码 → 数据包发送
|
错误处理机制
所有错误通过 CmdError(0xFFFF)单一通道 + ErrorCode 枚举:
| 错误码 |
场景 |
客户端表现 |
| FileNotFound (1) |
文件不存在 |
Warning 提示 |
| PermissionDenied (2) |
权限不足 |
Warning 提示 |
| FileBusy (8) |
文件被占用 |
Warning 提示 |
| ReadError (4) |
读取失败 |
Warning 提示 |
错误响应自动转发到对应的对话框(下载/打开),用户确认后自动关闭。
构建说明
环境要求
- Visual Studio 2022
- CMake 3.20+
- Qt 5.12.12 (msvc2017_64)
- Git
编译
1 2 3 4 5 6 7
| cmake -B build cmake --build build --config Release
cmake -B build -DBACKGROUND=ON cmake --build build --config Release
|
运行
1 2 3 4 5 6 7 8 9 10 11
| build/server/Release/RemoteCtrlServer.exe [port]
build/client/Release/RemoteCtrlApp.exe
build/server/Release/RemoteCtrlServer.exe [port] --install
build/server/Release/RemoteCtrlServer.exe [port] --uninstall
|
项目结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| RemoteCtrl/ ├── CMakeLists.txt # 顶级构建配置 ├── cmake/ │ └── FindCoronet.cmake # find_package → add_subdirectory 回退 ├── common/ # 共享库 (remotectrl_common) │ ├── Protocol.hpp # 命令枚举、错误码、常量 │ ├── Checksum.hpp/.cpp # CRC32C 校验 │ ├── Packet.hpp/.cpp # 包序列化/反序列化 │ └── Log.hpp # 统一日志模块(轮转文件输出) ├── server/ # RemoteCtrlServer │ ├── RemoteCtrlServer.cpp # 入口 + daemon + autostart │ ├── ServerApp.hpp/.cpp # acceptor 循环 │ ├── SessionHandler.hpp/.cpp # 协程读写 + 命令分发 │ ├── FileManager.hpp/.cpp # Qt 文件操作 │ ├── ScreenCapture.hpp/.cpp # GDI 截图 + WIC JPEG │ └── InputForwarder.hpp/.cpp # 鼠标转发 + 锁屏 └── client/ # RemoteCtrlApp (Qt5) ├── RemoteCtrlApp.cpp ├── MainWindow.hpp/.cpp # 主界面 + 包路由分发 ├── ClientNetwork.hpp/.cpp # coronet 收发分离 + Qt 桥接 ├── MonitorWindow.hpp/.cpp # 远程桌面 + 鼠标转发 ├── DownloadDialog.hpp/.cpp # 下载进度 + 错误弹窗 ├── FileBrowserWidget.hpp/.cpp # 目录树(懒加载) └── FileListWidget.hpp/.cpp # 文件列表 + 右键菜单
|
License
MIT