ykxmz 1.5.0:修复手表端 TLS 证书校验 + MTU 修复网络稳定性

被控端
- 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%)
- 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败)
- 每分钟回头找局域网,自动切回快 400 倍的路径
- 画面心跳帧:静止时省流量,客户端仍知道流是活的
- 锁屏时给出可操作的提示

手表端
- 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException
- 连接错误翻译成人话(证书/时间/解析/超时分别提示)
- 经中转连上后用服务器报的地址刷新已配对记录
- 新增局域网连接页面、服务器延迟检测

服务器端
- 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502)
- 网络调优脚本 net-tune.sh(开机自动应用)
- 管理页:批量删除、网络体检、下载区
- 隧道改 HTTP/2 + 双连接

文档
- 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
This commit is contained in:
xmz7891
2026-10-06 19:01:05 +08:00
commit b62ac865ea
3195 changed files with 203292 additions and 0 deletions
+221
View File
@@ -0,0 +1,221 @@
# -*- coding: utf-8 -*-
"""统一打包:被控端 + 手表端(已内置诊断)+ 文档。
注意:遥控诊断原来是一个单独的 App,现在已合并进手表主程序
(主界面 ->「设备诊断」按钮),所以不再单独出 APK。
产物(都在 dist/):
ykxmz-Windows.zip 被控端(解压即用,内含工具箱)
LanRemote-Watch-1.3.0.apk 手表控制端(含设备诊断)
LanRemote-1.3.0-完整包.zip 以上全部 + 预览图 + 文档
被控端目录结构(解压后):
LanRemote-Agent/
├── (已移除) <- 双击这个,所有功能都在菜单里
├── ykxmz.exe
├── _internal/
├── xffhq.bat
├── wlzj.bat / .py
├── 使用说明.txt
└── 先看这个.txt
"""
from __future__ import annotations
import shutil
import sys
import zipfile
from pathlib import Path
VERSION = "1.4.0"
ROOT = Path(__file__).resolve().parent.parent
DIST = ROOT / "dist"
EXE_DIR = ROOT / "dist_exe" / "ykxmz"
TOOLS = ROOT / "tools"
PREVIEW = ROOT / "dist_preview"
README = ROOT / "README.md"
TEST_REPORT = DIST / "测试报告.txt"
APK = DIST / f"LanRemote-Watch-{VERSION}.apk"
AGENT_ZIP = DIST / "ykxmz-Windows.zip"
BUNDLE = DIST / f"LanRemote-{VERSION}-完整包.zip"
# 会被放进被控端目录的工具(工具箱必须排第一)
TOOL_FILES = (
"fxfhq.bat",
"wlzj.bat",
"xffhq.bat",
)
QUICKSTART = f"""========================================================
局域网遥控 · 被控端(Windows) 版本 {VERSION}
========================================================
*** 不需要装 Python ***
这个目录里的 ykxmz.exe 是编译好的独立程序,
拷到任何一台 Windows 电脑上双击就能跑。
【装完之后怎么用】
1) 双击 ykxmz.exe
2) 弹出一个小窗口,让你输入 6 位数字(配对码)
自己定一个记得住的,比如 789113
下面有两个勾:
[x] 设置开机自启(开机后自动在后台运行)
[x] 顺便放行防火墙(需要管理员确认一次)
3) 点「确定,开始使用」
→ 会弹一次 Windows 的管理员确认(UAC),点「是」
→ 黑色终端窗口一闪,它在一键修复防火墙
→ 窗口全部消失,程序转入后台静默运行
4) 手表上打开 App → 点「自动搜索电脑」→ 点搜到的电脑
→ 输入你设的 6 位数字
5) 以后开机就直接在后台跑,屏幕上什么都没有;
手表打开 App 会自动连上,数字都不用再输。
【目录里这几个文件】
ykxmz.exe 主程序。双击就是上面第 1 步。
wlzj.bat 网络自检。连不上时跑它,看手表的包到底有没有到电脑。
xffhq.bat 一键修复防火墙。右键 →「以管理员身份运行」。
fxfhq.bat 同上,是程序自动生成的放行脚本,也可以右键提权运行。
先看这个.txt / 使用说明.txt 就是本文。
三个 .bat 都不需要装 Python。
【连不上?按这个顺序来】
1) 确认被控端在跑
任务管理器里能看到 ykxmz.exe
没有的话:ykxmz.exe --setup
2) 右键 xffhq.bat →「以管理员身份运行」,点「是」
3) 还不行 → 双击 wlzj.bat(网络自检)
它会监听 90 秒,看手表的请求有没有到达这台电脑:
收到连接 -> 网络是通的,问题在电脑这边
一直没动静 -> 包没到电脑,多半路由器开了「AP 隔离」
4) 手表上:首页「连不上?点这里诊断」
【命令行参数】(一般用不到)
ykxmz.exe --setup 重新打开设置窗口
ykxmz.exe --silent 直接静默运行
ykxmz.exe --add-device 10 静默运行 + 开放 10 分钟配对
ykxmz.exe --autostart on|off 开关开机自启
ykxmz.exe --status 看当前状态
ykxmz.exe --netcheck 90 网络自检(同 wlzj.bat)
ykxmz.exe --fix-firewall 提权修复防火墙
ykxmz.exe --reset-devices 清空已配对设备
【关于安全】
配对码是你自己设的,只存在这台电脑的 data\\settings.json 里。
一台设备都没配对过时配对是开着的(否则你设完码会连不上自己);
第一台配对成功后自动关闭。
配错 10 次锁 5 分钟(按来源 IP 分别计,别人锁不住你)。
屏幕共享时右下角会出现一条红色小提示 ——
这是故意的:有人在看你的屏幕时,屏幕前面的人应该知道。
"""
def clean_runtime_state() -> None:
"""打包前清掉运行时产生的东西,保持交付干净。"""
for name in ("data", "received"):
target = EXE_DIR / name
if target.exists():
shutil.rmtree(target, ignore_errors=True)
print(f" 已清理 {target.relative_to(ROOT)}")
for stale in ("fxfhq.bat",):
path = EXE_DIR / stale
if path.exists():
path.unlink()
print(f" 已清理 {stale}")
def install_tools() -> list[str]:
installed = []
for name in TOOL_FILES:
source = TOOLS / name
if source.is_file():
shutil.copy2(source, EXE_DIR / name)
installed.append(name)
else:
print(f" [警告] 缺少工具: {name}")
return installed
def zip_dir(source: Path, target: Path, arc_prefix: str = "") -> int:
files = [p for p in source.rglob("*") if p.is_file()]
with zipfile.ZipFile(target, "w", zipfile.ZIP_DEFLATED, compresslevel=6) as zf:
for path in files:
rel = path.relative_to(source)
arc = str(Path(arc_prefix) / rel) if arc_prefix else str(rel)
zf.write(path, arc)
print(f" {target.name} ({target.stat().st_size / 1048576:.1f} MB, {len(files)} 个文件)")
return len(files)
def main() -> int:
missing = []
if not EXE_DIR.is_dir():
missing.append(f"被控端产物目录 {EXE_DIR}(先运行 windows\\build_exe.ps1)")
if not APK.is_file():
missing.append(f"{APK.name}(先运行 android\\build_apk.ps1)")
if missing:
print("缺少产物:")
for item in missing:
print(f" - {item}")
return 1
DIST.mkdir(parents=True, exist_ok=True)
print("清理测试残留:")
clean_runtime_state()
print("\n安装工具到被控端目录:")
installed = install_tools()
for name in installed:
print(f" + {name}")
(EXE_DIR / "使用说明.txt").write_text(QUICKSTART, encoding="utf-8")
(EXE_DIR / "先看这个.txt").write_text(QUICKSTART, encoding="utf-8")
print(" + 使用说明.txt / 先看这个.txt")
print("\n打包被控端:")
count = zip_dir(EXE_DIR, AGENT_ZIP, arc_prefix="ykxmz")
print("\n打包完整交付:")
with zipfile.ZipFile(BUNDLE, "w", zipfile.ZIP_DEFLATED, compresslevel=6) as zf:
zf.writestr("先看这个.txt", QUICKSTART)
zf.write(APK, f"1-手表控制端/{APK.name}")
zf.write(AGENT_ZIP, f"2-电脑被控端/{AGENT_ZIP.name}")
if PREVIEW.is_dir():
for shot in sorted(PREVIEW.glob("*.png")):
zf.write(shot, f"3-界面预览/{shot.name}")
if README.is_file():
zf.write(README, "使用说明.md")
if TEST_REPORT.is_file():
zf.write(TEST_REPORT, "测试报告.txt")
print(f" {BUNDLE.name} ({BUNDLE.stat().st_size / 1048576:.1f} MB)")
print("\n" + "=" * 62)
print(f"交付内容(版本 {VERSION}):")
for path in (APK, AGENT_ZIP, BUNDLE):
print(f" {path.stat().st_size / 1048576:7.2f} MB {path.name}")
print(f"\n被控端包内含 {count} 个文件,工具箱等 {len(installed)} 个工具已就位。")
print("遥控诊断已合并进手表主程序,不再单独出包。")
return 0
if __name__ == "__main__":
sys.exit(main())