1
0
0

自用游戏客户端开发记录(1)

2026-10-30
2026-10-30
文章摘要
|

开发复盘 · 记录范围截至 2026 年 10 月 28 日

我已经有一条质量较好的专线和 Shadowsocks 节点,希望把它用在外服游戏上。最初以为,识别游戏进程,再把流量交给 sing-box,应该就能完成一个实用的加速工具。

真正开始做之后,问题逐渐扩展到启动器、网页组件、短命进程、管理员权限、多目标规则,以及异常退出后的网络恢复。GameRoute 就是在这些实际问题中,从炉石传说的命令行原型,逐步发展成通用 Windows 图形客户端的。

这篇文章根据项目开发与测试记录整理,侧重需求如何改变设计。本次整理没有重新读取源码或运行网络测试;文中的完成状态和验收结论均以提供的记录为依据。

线路已经具备,客户端还要解决什么?

项目起点是已有的腾讯云内网级专线和代理节点,所述端到端链路延迟在 5ms 以内。这个数字描述的是已有线路条件,不能直接当作游戏服务器延迟,也不能算作 GameRoute 的实测加速成绩。项目当时还没有形成完整的游戏延迟、抖动与丢包率对照实验。

现有 Clash 类客户端在我的使用场景中不够顺手。选择 sing-box 之后,桌面客户端需要解决的工作也逐渐明确:找到真正联网的程序,覆盖游戏依赖的组件,把目标流量交给节点,让其他流量默认直连,再把配置、启停和故障排查做成普通用户能够操作的流程。

最初以外服炉石传说为切入点,是为了有一个具体的验证对象。随后需求扩展为任意 Windows 游戏,并要求完整图形界面、内置内核、可编辑游戏档案,以及尽可能自动识别关联程序。项目采用 C#、WPF 和 .NET Framework 4.7.2,面向 Windows 10/11 x64;记录中的构建内置 sing-box 1.14.1。

第一次重要修正:选择启动器,并不等于覆盖登录流量

一个很有代表性的问题出现在战网登录:导入节点并加速暴雪登录器后,仍然无法登录,诊断里显示节点关联连接为零。

这让我重新审视“选择一个程序”到底意味着什么。用户看到的是启动入口,但真正负责联网的可能是另一个程序。引导程序启动实际客户端后就退出,登录、内嵌网页、更新下载又可能分别交给不同组件。

后续处理将明确选择的平台客户端及其已知网络组件纳入范围,包括实际客户端、网页组件和 Agent,同时处理版本路径变化,以及引导程序退出后会话仍需维持的问题。修复之后,实际使用反馈登录成功,项目记录中也出现了战网的 login complete。

这个结果证明了对应战网登录场景得到修复。炉石完整对局、其他战网游戏,以及不同网络状态下的行为,还需要各自验证。

这次问题也让产品中的两个概念变得清楚:启动入口决定从哪里启动,加速目标决定哪些程序的流量经过节点。选择单个游戏时,应尽量限定关联流量;明确选择整个平台时,则需要说明登录、网页、更新与下载也可能一起经过节点。

自动识别进程,需要处理迟到、缺失和身份复用

最直观的关联办法,是从游戏进程沿父子关系追踪。对于关系清晰的程序,这个办法有效。但 Windows 上的启动过程会让它很快遇到边界:父程序可能瞬间退出,子进程事件可能先到,启动器可能经过多层交接,PID 还可能被新程序复用。

因此,进程识别逐步发展为结合事件与定时快照,并加入原生快照回退。进程实例证据同时考虑 PID 和创建时间,历史实例缓存保留已经退出的关联线索,待确认事件队列则用于补偿跨批次到达的父子关系。

这些缓存都有容量和时间限制;溢出、信息不可读等情况也需要被记录。否则,一方面可能长期占用资源,另一方面会让界面看起来一切正常,实际却已经失去部分观测能力。

自动关联需要证据强度和失败边界。身份信息不足时,应显示观测不足,避免把无关程序加入规则。

无父子关系的独立辅助程序、独立服务,以及真实反作弊环境中的归属判断,仍然存在未完成的部分。可编辑组件档案提供了人工确认和预加载入口,但不能据此宣称自动识别已经覆盖所有游戏。

炉石加上战网,让单目标会话变成多目标会话

接下来的需求很自然:炉石依赖战网,实际使用时需要同时加速游戏和平台。于是,客户端从单个目标扩展为一个会话选择多个目标,共用首页选定的节点。

界面可以选择炉石作为主目标,再勾选战网作为附加目标,并保存选择以便下次恢复。但底层工作的变化远大于增加一个多选列表。

规则合并时,需要保留共享程序路径与目标网段之间的配对关系,检查不同档案之间的路径、进程名和网段限制冲突。更新一个目标时,要保留其他目标的规则;更新失败时,还要恢复相应学习状态。

会话退出条件也随之变化。常驻的战网客户端可能一直运行,不能让它无限延长游戏会话;另一方面,一个目标退出,也不能使仍在运行的游戏被提前断开。进程快照受到权限限制时,“看不见进程”还不能直接等同于“游戏已退出”。

现有实现已经为多个目标分别跟踪主进程、子进程与退出宽限期。更细的主游戏、登录器、更新器和辅助程序角色划分,仍然需要继续完善。目前支持多个目标共用一个节点;各目标分别使用不同节点,以及共享平台连接按游戏动态归属,属于后续扩展范围。

权限分离之后,停止和恢复成为设计的一部分

随着 TUN、进程观测与网络恢复能力加入,权限处理成为架构问题。最终采用的方式是:图形界面保持普通用户权限,在开始加速时临时启动管理员后台。

部分承担的工作
普通权限界面管理节点、目标、组件、配置与诊断。
识别与规则管理发现游戏、关联进程、合并规则与检查冲突。
临时管理员后台执行需要权限的观测、TUN 管理与恢复操作。
sing-box 内核按生成配置处理连接与 TCP/UDP 转发。
本地存储保存设置、加密节点密码与脱敏诊断摘要。

界面与后台通过本机命名管道通信,并检查通信双方身份、进程实例与权限状态。后台只接受限定操作,对节点字段、路径、网段和规则数量进行验证。内置内核释放到受保护目录后进行校验,并通过 Windows Job Objects 管理进程生命周期。

清理需要覆盖正常停止、内核退出、管理员后台退出、管道断开和普通客户端被强制结束等路径;下次启动时,还要检查上次遗留的恢复记录。停止失败时,需要保留可重试状态,并让用户看到清理失败,而不是直接丢掉后台信息。

做到这里,“启动成功”的定义已经不够用了。加速客户端还必须解释会话如何结束,以及结束后本机网络是否恢复。TUN 能建立,只是整个生命周期的开始。

诊断里的数字,也需要说明它能证明什么

早期的“连接为零”说明,用户需要知道目标流量有没有命中规则。之后,诊断逐渐加入进程文件名、协议、出口、规则类型、采样流量与错误分类。

但一个连接计数仍然可能造成误解。短连接可能被轮询漏掉,API 读取失败可能看起来像没有流量,历史记录可能被误读为活动连接,而错误日志又未必包含足够的进程信息。

因此,后续增加了会话标识、采样时间、有效性、过期提示和结束原因。诊断缓存采用有界轮换,优先展示活动连接;缺少关联证据的错误明确标记为归属未知。日志读取也处理了跨块 UTF-8 解码、部分行与末行、截断、超长行以及损坏字节恢复。

摘要约每 15 秒尝试保存一次,停止时再次保存,并展示保存失败与历史清除入口。这些改进的目的,是让诊断能够描述当时观察到了什么,以及哪里仍然存在缺口。

  1. 规则已经生成:说明配置中包含目标。
  2. 观察到连接经过指定出口:说明对应连接命中了预期路径。
  3. 应用请求成功:说明特定业务操作完成。

这三个层次不能互相替代。旧日志里的超时与 TUN 回环仍未完全确定根因,分类和统计改善了排查条件,也还需要可复现的回归用例。

节点测试:把配置排查放到开始加速之前

节点测试是后续补上的一项完整能力。用户可以直接测试编辑器中的配置,无需先保存;密码框留空时,沿用所选已保存节点的密码。修改配置或切换节点后,旧结果会清除,避免把旧配置的成功结果误套到新配置上。

测试使用临时本地回环代理和内置 sing-box,分别检查 HTTPS 与原生 UDP DNS,两项都通过才给出整体通过。测试不创建 TUN、不修改系统代理,也不写入明文测试配置或测试日志。

探测检查内容解释范围
HTTPS访问 www.gstatic.com/generate_204,建立代理连接、校验 TLS 并读取 HTTP 响应。确认 TCP 与 HTTPS 路径可达;收到有效响应不代表任意业务请求都成功。
UDP DNS向 1.1.1.1:53 查询 example.com 的 A 记录,核对响应身份与内容。确认对应 UDP 请求能够往返,并拒绝错误事务 ID、错误码、空答案和截断响应等情况。

每项网络探测设置十秒期限。测试期间限制冲突操作,用户可以取消;关闭窗口时也会先取消并等待清理。临时内核同样由作业对象管理,并在结束时等待退出。

本地模拟 Shadowsocks 的测试覆盖了成功、TCP 失败、UDP 超时、错误 DNS 响应、无效 TLS、取消和内核配置错误等十二种场景,同时检查测试内核与日志是否残留。

这里也有验收边界:成功路径使用本地 HTTP 服务,TLS 用例验证无效响应会被拒绝,因此不能替代真实节点上的 HTTPS 成功测试。界面中的耗时包含连接与协议握手,也不能当作游戏内延迟。

测试开发还遇到过 UDP 端口绑定失败。排查发现,随机选择的端口落入 Windows 的 UDP 排除端口范围。随后改为先申请可用 UDP 临时端口,再在同一端口号上建立 TCP 服务。这个问题提醒我,网络测试失败也需要检查测试环境本身。

界面改动来自真实使用,而不是功能数量

多目标功能加入后,首页曾采用展开式勾选列表。实际使用时,这个列表占用了太多垂直空间,把节点选择与启动按钮不断往下推。

最后将附加目标改为与主游戏选择框风格一致的紧凑下拉多选:收起时显示选择摘要,展开后可以连续勾选和取消,长名称省略显示并提供悬停提示,按 Esc 收起。原有的选择保存、恢复和会话锁定逻辑继续沿用。

同时,移除了“添加 Steam 客户端测试”这样的专用开发入口,保留普通 Steam 游戏扫描与已有平台组件能力。用户取消的 TODO 条目也应记录为范围调整,不能算成已实现功能。

这类改动没有增加新的代理能力,却直接影响日常操作。图形客户端的价值,既包含底层规则正确,也包含用户能否迅速理解并完成一次加速。

测试结论要跟着构建走

项目逐步形成了多层验证:确定性规则与生命周期测试、本机进程快照和事件测试、实际 sing-box 的匹配与热更新、本地模拟 Shadowsocks、管理员权限下的隔离 TUN,以及用户实际战网登录反馈。

它们各自回答不同的问题。尤其在连续修改界面、诊断和生命周期之后,不能把早期构建的网络验收自动转移到最新文件上。

阶段记录中的验证适用边界
前序可靠性构建管理员进程事件检查,以及 full、disconnect、client-crash 三类隔离 TUN 验证,涉及 IPv4/IPv6 TCP/UDP、目标代理、无关进程直连、热更新和清理。结论绑定当时构建与测试环境。
节点测试构建常规检查 18 组通过、1 组跳过,包含十二种节点测试模拟场景。普通权限下的 Windows 进程事件检查跳过,未计为通过。
附加目标下拉多选构建重新编译,完成界面回归与渲染截图检查,包括选择恢复、取消选择与 Esc 收起。没有重新执行完整网络、真实节点与 TUN 验收。

最后一版界面构建记录中的 SHA256 为:

755C1EA3FCEB96FA3F2B5D0EACA4B45763F5725BD37CAEB3651BEE605230653A

它用于标识记录中的交付文件,本次整理未重新计算该哈希。构建当时没有编译错误,仍有两条既有字段未赋值警告。

公开源码与本地数据,需要分开管理

项目始终保留一个明确要求:GitHub 上传源码、测试和文档,打包程序、下载的内核、本地配置、节点凭据与原始日志不进入仓库。节点密码使用 Windows 当前账户加密,诊断导出与游戏档案导出也需要说明各自包含什么。

尤其是游戏档案可能包含个人安装路径,不能与可公开的诊断摘要混为一谈。历史记录里有源码推送与隐私检查,但截至整理所依据的记录,本地仍有未提交修改和新增文件。因此,“本地已实现”与“GitHub 已发布”必须分别描述。

类似地,清理 dist 旧产物虽被提出,但可见记录中尚无成功删除后的验证结果,也不应写成已经完成。提交标题、完成说明和实际代码行为之间,都需要有可核对的证据。

下一步:把可用性推进到长期可靠

GameRoute 已经从专用原型发展出通用客户端的主要结构。后续工作仍集中在真实使用条件下的可靠性:

  • 复现超时与 TUN 回环,建立能够稳定触发的回归用例。
  • 对最终交付构建补充快速启停、启动取消、启动时关窗及故障恢复验收。
  • 验证真实节点故障前、故障中和恢复后的 TCP/UDP 行为,以及真实游戏完整对局。
  • 继续完善独立组件与服务归属、组件生命周期、学习记录身份及更新失效判断。
  • 补充进程事件压力、长期资源消耗、日志轮转、休眠唤醒、网络切换与反作弊兼容性测试。

FlClash 与多 VPN 共存按需求暂缓,现有冲突提示只是当前处理策略。真实游戏的性能收益,也需要通过延迟、抖动与丢包率的对照实验来回答。

回看整个过程,最初的进程识别需求被战网登录问题推进为平台组件管理,炉石与战网组合使用又推动了多目标规则和会话设计。权限问题推动前后台分离,诊断局限推动证据说明,异常退出测试则推动网络恢复机制。

已有优质线路,为 GameRoute 提供了起点。客户端接下来的工作,是让每一次选择、连接、停止和失败,都有清楚的行为与能够核对的结果。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

评论