Files
SimpleRemoter/docs/FileTransferSpeed_Design.md
T
yuanyuanxianganddeepseek-v4-pro 76decec0fe Feature: Add file-transfer speed dialog with multi-language support
Add a novice-friendly "File Transfer Speed" dialog under the Advanced menu
that controls file-transfer speed in both directions without touching
SimplePlugins. Speed is passed through InitFileUpload's existing
chunkSizeKb/sendDurationMs arguments, so the precompiled library stays
untouched. Seven presets run from ~0.3 MB/s up to a new 10 MB/s tier plus an
unlimited tier; the chosen value is stored in [transfer] ChunkKb/DurationMs.

Upload reads THIS_CFG at the master's InitFileUpload (2015RemoteDlg.cpp:2225)
and takes effect on restart. Download is pushed to the client over a new
CMD_FILE_SPEED (252) command, sent from OnOnlineFileManager and
OnOnlineDesktopManager before each session opens, and read by all four client
InitFileUpload call sites via GetTransferSpeed so the process-global refcount
cannot latch a stale speed. All Chinese strings go through LangManager, with
en_US/zh_TW/de_DE entries added for the tier names, format strings and hint
text.

Co-Authored-By: deepseek-v4-pro
2026-10-02 19:57:57 +02:00

147 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# YAMA 文件传输速度调节设计
> **状态**:已实现(Windows 端,含多语言)。其他平台(Linux/macOS 客户端)暂不实施。
> **读者**:研发/评审人员。
> **关联文档**:[FILE_TRANSFER_V2.md](./FILE_TRANSFER_V2.md)(V2 协议)、[Mcp_FileTransfer_Design.md](./Mcp_FileTransfer_Design.md)(MCP 文件传输)。
---
## 1. 背景与目标
文件传输速度目前是**写死的**:`SimplePlugins` 库的 `InitFileUpload(key, msg, hmac, chunkSizeKb, sendDurationMs, ...)` 被 YAMA 所有调用点传 `64, 50`,折算 ≈ 1.25 MB/s。用户无法调节。
目标:在 YAMA 主菜单「高级」下新增一个**面向小白**的「文件传输速度」对话框——拖动滑块即完成设置,实时显示预估速度;**不修改 SimplePlugins 库**(库已编译,只通过其已暴露的 `chunkSizeKb`/`sendDurationMs` 两个入参控制)。
---
## 2. 速度原理(现状)
库内部把两个入参转成全局量(`SimplePlugins/file_upload.cpp:221-222, 849-850`):
```cpp
static int chunk_size = 64 * 1024; // 默认 64KB
static int send_duration = 50; // 默认 50ms
// InitFileUpload: chunk_size = chunkSizeKb * 1024; send_duration = sendDurationMs;
```
发送循环每发一块就 `Sleep(send_duration)`(V1 `FileBatchTransferWorker` 与 V2 `FileBatchTransferWorkerV2` 共用这对全局量):
```
预估速度 = chunkSizeKb * 1024 / (sendDurationMs / 1000) 字节/秒
默认 64KB / 50ms ≈ 1.25 MB/s
```
两个关键约束:
1. **速度只在 `InitFileUpload` 时设定一次**,库无运行时 setter(`g_threadCount > 1` 时提前返回,不会重设)。
2. **V1 / V2 共用同一对全局量**,一次设置同时覆盖 `COMMAND_SEND_FILE(68)` 与 `COMMAND_SEND_FILE_V2(85)` 两种协议。
---
## 3. 档位表(权威唯一来源,主控端对话框维护)
| 档位 | 名称 | chunkKb | durationMs | 预估速度 |
|---|---|---|---|---|
| 0 | 最慢 | 64 | 200 | ≈ 0.3 MB/s |
| 1 | 慢 | 64 | 100 | ≈ 0.6 MB/s |
| 2 | 默认 | 64 | 50 | ≈ 1.25 MB/s |
| 3 | 快 | 128 | 50 | ≈ 2.5 MB/s |
| 4 | 更快 | 256 | 50 | ≈ 5 MB/s |
| 5 | 很快 | 512 | 50 | ≈ 10 MB/s |
| 6 | 不限速 | 1024 | 0 | 网络上限 |
- 滑块 `CSliderCtrl` 范围 `0..6`,`SetPageSize(1)`,默认落在 2。
- `durationMs = 0` 表示不人为限速(`Sleep(0)` 仅让出时间片,实际受带宽约束)。
- **注意 Windows `Sleep` 粒度 ≈ 15.6ms**:`durationMs` 低于约 15ms 基本等同不限速。故档位要么 ≥ 20ms,要么直接 0ms,不设 5ms 之类的“名不副实”中间值。
预估文案:`当前约 1.25 MB/s`;`durationMs==0` 显示 `不限速(受网络带宽约束)`。
- **多语言**:档位名(最慢/慢/默认/快/更快/很快/不限速)与预估格式串(`%s · 约 %.2f MB/s`、`%s · 不受限速(受网络带宽约束)`)经 `_TR`/`_LF` 走 `LangManager` 翻译表;语言文件以中文原文为 key。刻度标签拆成 最慢/默认/不限速 三个独立 `LTEXT` 以便各自翻译(英文宽度不同,不能靠空格对齐)。
---
## 4. 两个方向的生效链路
文件传输有两条方向,`InitFileUpload` 各自在不同进程/时机调用:
| 方向 | 发送方 | `InitFileUpload` 调用点 | 生效方式 |
|---|---|---|---|
| 上传(主控端 → 被控端) | 主控端 | `server/2015Remote/2015RemoteDlg.cpp:2223`(启动一次) | 读 `THIS_CFG`,重启主控端生效 |
| 下载(被控端 → 主控端) | 被控端 | `client/FileManager.cpp:40`(CFileManager 构造,每会话一次) | 读客户端配置,下次打开文件管理会话生效 |
### 4.1 上传方向(主控端本地,无协议改动)
`2015RemoteDlg.cpp:2223` 现为 `InitFileUpload({},{},GetHMAC(),64,50,Logf,GetUpperHash())`,改为读 `THIS_CFG`:
```cpp
int chunkKb = THIS_CFG.GetInt("transfer", "ChunkKb", 64);
int durMs = THIS_CFG.GetInt("transfer", "DurationMs", 50);
InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
```
### 4.2 下载方向(需下发到被控端)
新增命令 `CMD_FILE_SPEED`,照 `CMD_QUALITY_LEVEL(78)` 的“服务端下发 → 客户端持久化 → 本地生效”套路:
1. **`common/commands.h`**:新增 `CMD_FILE_SPEED = 252`(命令号单字节,252 < 255 安全)。
2. **命令格式**:`[cmd:1][chunkKb:uint16 LE][durationMs:uint16 LE]`,共 5 字节。
- 传原始 `chunkKb`/`durationMs` 而非档位索引,**避免客户端复制映射表**,映射表只存在于主控端对话框。
3. **主控端下发**:在 `OnOnlineFileManager()`(`server/2015Remote/2015RemoteDlg.cpp:4737`,发 `COMMAND_LIST_DRIVE` 开文件管理会话)发 `COMMAND_LIST_DRIVE` **之前**,先经主连接把当前档位 `CMD_FILE_SPEED`(5 字节)发给被控端;`OnOnlineDesktopManager()`(`2015RemoteDlg.cpp:4723`,发 `COMMAND_SCREEN_SPY`)同理也发一次,覆盖“先开远程桌面再开文件管理”的引用计数时序。两处都在 `SendFileSpeedCommand()`(`:9310`)统一读取并下发。
4. **被控端接收**:在客户端主连接分发 `client/KernelManager.cpp:814` 的 `switch`(`COMMAND_LIST_DRIVE` 所在,`case` 加在 `1280` 附近)加 `case CMD_FILE_SPEED`,把两数写入 `iniFile cfg(CLIENT_PATH)` 的 `[transfer]` 节。
5. **被控端调用点读配置**:`client/FileManager.cpp:40`(CFileManager 构造)改为读 `cfg.GetInt("transfer","ChunkKb",64)` / `DurationMs`,替换硬编码 `64, 50`。CFileManager 每会话重建(构造 Init、析构 Uninit),故下次打开文件管理即生效。
> **关键**:库用进程级引用计数,速度只在**首次** `InitFileUpload` 时设定(`g_threadCount > 1` 时提前返回,不重设)。客户端共 4 个 `InitFileUpload` 调用点(`FileManager.cpp:40`、`ScreenManager.cpp:109`、`ScreenManager.cpp:873`、`KernelManager.cpp:1399`),谁先初始化谁锁定速度。故**这 4 处必须全部改为读同一配置**,否则下载速度会被先初始化的管理器(如远程桌面会话)锁成旧值。
---
## 5. 配置存储
- 主控端:`THIS_CFG`(ini)`[transfer]` 节 `ChunkKb` / `DurationMs`(int)。
- 被控端:`iniFile(CLIENT_PATH)` 的 `[transfer]` 节 `ChunkKb` / `DurationMs`(int),由 `CMD_FILE_SPEED` 写入。
存 `ChunkKb`/`DurationMs` 两个 int 而非档位索引:自解释、直接对应 `InitFileUpload` 入参、不易错位。
---
## 6. 改动文件清单(Windows 端)
| 文件 | 改动 |
|---|---|
| `server/2015Remote/resource.h` | 加 `IDD_FILE_SPEED`、`ID_TOOL_FILE_SPEED`、`IDC_FSPEED_SLIDER`、`IDC_FSPEED_LABEL`、`IDC_FSPEED_RESET` |
| `server/2015Remote/2015Remote.rc` | 「高级」菜单加一项;新增对话框资源(滑块+预估标签+按钮)。**文件为 UTF-16LE 编码,须按 Unicode 读写** |
| `server/2015Remote/CFileSpeedDlg.h` | 新建:档位表 + `OnHScroll` 实时预估 + 恢复默认(照 `CPreviewLevelsDlg.h` 内联实现) |
| `server/2015Remote/2015RemoteDlg.h` | 加 `OnFileTransferSpeed()` 声明 |
| `server/2015Remote/2015RemoteDlg.cpp` | 消息映射 `ON_COMMAND(ID_TOOL_FILE_SPEED, ...)`;`2223` 读配置(上传);`OnFileTransferSpeed()` 弹出对话框并写回 THIS_CFG;`OnOnlineFileManager()`/`OnOnlineDesktopManager()` 发 `CMD_FILE_SPEED` |
| `common/commands.h` | 加 `CMD_FILE_SPEED = 252` |
| `client/KernelManager.cpp` | `case CMD_FILE_SPEED` 写客户端配置(主连接 switch,`814`) |
| `client/FileManager.cpp`、`client/ScreenManager.cpp`、`client/KernelManager.cpp` | 4 个 `InitFileUpload` 调用点读配置替换硬编码 `64, 50`(引用计数要求全部一致) |
| `server/2015Remote/lang/en_US.ini`、`zh_TW.ini`、`de_DE.ini` | 追加「文件传输速度」相关 13 条中文原文→译文(GBK 编码,`RCDATA "lang\*.ini"` 由 rc.exe 嵌入) |
---
## 7. 生效时机与提示文案
- 上传速度:重启主控端生效。
- 下载速度:下次打开该主机的文件管理会话生效。
- 对话框保存后弹提示:`文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。`
---
## 8. 风险与备注
1. **`Sleep` 精度**:Windows 计时器粒度约 15.6ms,`durationMs` 过小则失真(见 §3)。
2. **实际速度 < 预估**:预估为纯 `chunk/delay` 理论值,未计入 `f()` 网络发送耗时;对话框文案用“约/大概”表述。
3. **命令号冲突**:`CMD_FILE_SPEED=252` 需确认 `commands.h` 无重号;252 < 255(单字节 `uint8_t cmd` 上限)。
4. **`.rc` 编码**:`2015Remote.rc` 为 UTF-16LE(带 BOM),编辑必须按 Unicode 处理,避免破坏资源脚本。
5. **跨平台**:Linux/macOS 客户端下载路径暂不改(`CMD_FILE_SPEED` 会被老/其他平台客户端静默忽略,向后兼容)。
6. **多语言 key 精确匹配**:语言文件为 GBK 编码、key 不 trim(`CIniParser` 保留原始空格);译文 key 必须与源码逐字一致——源码为 UTF-8、经 `/execution-charset:.936` 编译为 GBK,`·`(U+00B7)、全角括号()等需一致,否则查不到翻译。
---
## 9. 实施顺序
1. `common/commands.h` 加命令号 → `resource.h` 加 ID → `.rc` 加菜单项与对话框资源。
2. 新建 `CFileSpeedDlg.h` → `2015RemoteDlg` 接线(上传方向,可先验证)。
3. 主控端下发 `CMD_FILE_SPEED` → 客户端接收持久化 → 客户端调用点读配置(下载方向)。
4. 编译验证(MSBuild 须传 `-p:SolutionDir`,见项目记忆)。