生命周期
新建 ──▶ 运行中 ──「关闭」──▶ 已停止 ──「启动」──▶ 运行中
│
├─「修改」──▶ 已停止(配置已更新)
└─「删除」──▶ 记录消失
关键点:关闭不等于删除。
状态是怎么来的
- 列表每 3 秒轮询一次
list_tunnels。 - 后端同时监听 ssh 进程退出,一旦退出立即广播
tunnel-exited,界面马上转「已停止」,不用等下一轮轮询。 - 「运行中」的判定是:PID 非 0,且该 PID 的进程名确实是
ssh。只查 PID 是否存在,会把「PID 被系统复用」误判成运行中。
关闭
点「关闭」之后:
- 先优雅终止(Windows
taskkill,UnixSIGTERM)。 - 最多等 1.8 秒。
- 还在跑就强制结束(
taskkill /F/SIGKILL)。 - 记录保留,PID 清零,状态变成「已停止」。
如果发现 PID 已经被别的程序复用,应用不会去杀那个进程,只把记录标记为已停止——宁可留下一个可能已经死掉的 ssh,也不误杀别人的程序。
启动
「启动」用保存的配置重新拉起 ssh,走的是和新建完全一样的链路:端口预检、密码探测、监听判定。所以:
- 本地端口已经被别的进程占了,会在启动前就报错,并指出占用者。
- 需要密码时同样弹框,并且在建立隧道前先做一次认证预检。
修改
只有「已停止」的记录能改,可以改 Host、绑定地址、本地端口、远程主机与端口。
- ID 和创建时间不变。
- 只改配置,不涉及进程。
- 新端口如果和其他运行中的记录冲突,会被拦下。
删除
只有「已停止」的记录能删。删除不可撤销——记录和配置一起消失,ssh 进程本来就已经不在了。
为什么关闭和删除要分开 一条转发往往要反复开关。如果关闭就删记录,每次都得重填四个字段;反过来,如果关闭时保留记录又容易忘记清理。所以「删除」被做成一个独立的、明确的操作。
托盘
| 操作 | 行为 |
|---|---|
| 点标题栏关闭(Windows) | 隐藏到托盘,隧道继续跑 |
| 左键托盘图标 | 显示 / 隐藏主窗口 |
| 右键 → 显示主窗口 | 同左键 |
| 右键 → 退出应用(保留隧道) | 退出应用,ssh 进程继续在后台 |
| 右键 → 退出应用(关闭隧道) | 退出前先关掉所有运行中的隧道 |
默认选项是「保留隧道」:应用退出不该替你做决定。
界面细节
- 深/浅主题在右上角切换,写入 localStorage,首帧前应用,不会闪白。
- 全局右键菜单被禁用(WebView2 默认菜单不再弹出),托盘的原生菜单不受影响。
- 操作结果通过右上角 Toast 提示,失败信息是后端原始的中文错误。
- 底部信息栏:左边计数,右边版本号、版权和数据目录入口(点击在资源管理器 / 访达中打开)。