上文粗略讲了舞萌开机初始化流程,本文深入讲下困扰不少人的机台联网部分
1. 总览
1.1 自检在开机链路中的位置
上篇初始化文章我们讲过 maimai 机台运行两套并行系统:amdaemon(原生后台服务,负责与运营服务器的全部通信)和 Unity 游戏程序(负责游戏)
开机按 6 步推进,网络自检是第 3 步(PowerOnProcess.WaitNetWork)。开机初始化画面逐行显示每项检查的状态:Check 初始化中 / Good 好 / NA 跳过 / Bad 坏
网络自检的目标是确认机台能否与服务器正常通信,前 5 项检查机台自身和局域网,后 4 项检查与服务器的连通与存活
1.2 链路总览
[开机] amdaemon 启动 └─ ALPB 开机自检驱动 └─ am::network::Tester 依次执行 9 项网络自检(am::networktest) 0 IpAddressChecker ← 本机 IP 有效性 1 GatewayChecker ← 网关连通性 2 DnsLanChecker ← DNS 配置有效性 3 HopsChecker ← 域名解析 + ICMP 路由跳数 4 LineTypeChecker ← 线路类型(LAN/WAN) 5 AllnetAuthChecker ← ALL.Net 认证 + 下载指令就绪(120s) 6 AimeChecker ← CHIME 微信 AIME 服务存活探活 7 EmoneyChecker ← 电子钱包(国服废项,NA) 8 AimePayChecker ← AimePay(国服废项,NA) │ 每项结果经回调上报 ▼ amdaemon app 侧 NetworkEventListener → 可用性标志(IP / Hops / AllnetAuth 三项) ▼ IPC (NamedPipe)[Unity] AMDaemon.Network.TestInfo / PowerOnTestInfo ▼ 每帧轮询 PowerOnProcess.WaitNetWork (item0 超时 15s / item5 Net 认证 120s)1.3 9 项速览
| item | 检查器类名 | 查什么 | 主要依赖 |
|---|---|---|---|
| 0 | IpAddressChecker | 本机 IP 是否有效(非 APIPA) | 本机 / DHCP |
| 1 | GatewayChecker | 能否 ping 通网关 | 本机内网 |
| 2 | DnsLanChecker | 系统 DNS 配置数量是否有效 | 本机内网 |
| 3 | HopsChecker | 目标域名能否解析 + ICMP 逐跳计数 | DNS + 目标域名 |
| 4 | LineTypeChecker | 线路类型是否为 LAN | 本机网络接口 |
| 5 | AllnetAuthChecker | ALL.Net 认证 + 下载指令就绪 | ALL.Net 服务器(120s) |
| 6 | AimeChecker | 会员服务器存活 | CHIME 服务器 |
| 7 | EmoneyChecker | Emoney 服务器存活(国服废项) | 无 |
| 8 | AimePayChecker | AimePay 服务器存活(国服废项) | 无 |
2. 机制基础
2.1 三层结构
| 层 | 角色 | 说明 |
|---|---|---|
| 原生引擎层(am::network) | 真正执行网络操作 | 内嵌各引擎检查器(IpAddr / Gateway / DnsLan / LocationRouter 等) |
| 检查器层(am::networktest) | 包装与判定 | 总 Tester 串起 9 个 item 检查器,每项持有对应引擎指针 |
| 游戏程序层(Unity C#) | 读取与显示 | 每帧轮询状态字,翻译为 Good / NA / Bad / Check |
网络操作的实际执行在 am::network::* 引擎类中完成;am::networktest::* 是包装层,负责驱动引擎并将结果上报给游戏程序
2.2 执行状态机
每个引擎检查器内部维护一个异步步进器(Waiter),生命周期为:
清空 → 入队(挂载检查目标)→ 启动→ 每轮步进 → 判断是否完成 → 取 OK/NG 标志 → 写出结果结果码:4 = OK(通过)、5 = NG(失败)、1 = 等待 / 跳过
2.3 item 检查器的核心字段
每个 item 检查器对象内含以下关键字段:
- item 编号(0–8)
- 状态槽:2 = OK,3 = 运行中
- 引擎结果快照:引擎完成后拷入,供判定逻辑读取
- 显示状态字:游戏程序每帧读取此字节,决定屏幕上显示什么
2.4 驱动循环
总 Tester 每轮依次遍历 9 个 item:
- 读当前 item 状态槽,已 OK 则跳过
- 首轮:拷入引擎结果快照,写状态”运行中”,触发回调
- 后续:持续步进引擎,直到结果就绪
- 九项全部完成后,Tester 总状态置为完成
2.5 shouldRun 谓词
每个 item 有一个 shouldRun 函数,决定该项是否需要运行。若返回 fake(如无对应配置目标),该项直接跳过,游戏侧显示 NA。国服 item7(Emoney)和 item8(AimePay)均因此固定返回 NA,直接就不显示该检测项目
3. 9 项逐一说明
3.0 IP 地址(IpAddressChecker)
引擎类:am::network::IpAddressChecker
判定逻辑:
读取本机网卡当前 IP 地址,按地址段判定:
169.254.x.x(APIPA)→ NG:这是操作系统在 DHCP 失败或网线断开时自动生成的临时地址,说明机台未获得有效 IP- 规定的私有地址段 → OK
- 网卡无配置(
ignore_unconnected开关触发)→ NA 跳过
超时:游戏程序侧对本项设 15 秒超时,超时直接判 Bad
3.1 网关(GatewayChecker)
引擎类:am::network::GatewayChecker(继承自 GatewayPreChecker)
判定逻辑:
向配置中的网关地址发送 ICMP ping,等待响应:
- ping 成功 → OK
- ping 失败 → 退避重试,间隔从 60 秒起逐次翻倍,上限约 900 秒(约 4 次重试),全部失败后判 NG
底层使用 ICMP 实现(altr_icmp),也就是说,能 ping 通网关路由器则通过;网关 IP 配错、交换机不通或网线物理断则最终 Bad
3.2 本地 DNS(DnsLanChecker)
引擎类:am::network::DnsLanChecker
判定逻辑:
读取配置中 DNS 服务器的数量,与系统中实际可查到的 DNS 数量对比:
- 实际数量满足配置要求 → OK
- 不满足(如 DNS 未下发或配置错误)→ 等待 / NG
底层调用系统 DNS 解析接口(amDnsInit / amDnsResolveNameA/W),配置里写了几个 DNS,系统里就得能查到几个,DNS 没配或 DHCP 没下发则挂
3.3 跳数(HopsChecker)
引擎类:am::network::HopsCounter(实际解析由 NameResolver 驱动)
判定逻辑:
- 对目标主机名进行 DNS 解析
- 解析成功后,通过 ICMP 逐跳计数
- C# 侧 item3 显示实际跳数
- DNS 解析失败 → NG
- 解析成功 → 显示跳数并 OK
前置依赖 item2(DnsLan)正常,域名能解析就过,同时显示路由跳数;解析不了则 Bad。
3.4 线路类型(LineTypeChecker)
引擎类:am::network::LocationRouterChecker
判定逻辑:
检测当前线路类型:
- LAN → OK
- WAN → NG,错误信息
Network type error(WAN)
引擎内部通过解析网络地址与子网掩码判断线路归属,底层依赖 NameResolver 解析目标地址
3.5 Net 认证(AllnetAuthChecker)
引擎类:alw_auth(ALL.Net 认证库)
判定逻辑(双条件,两者须同时满足):
- 认证通过 :与 ALL.Net 服务器完成认证握手
- 下载指令就绪:从服务器取得 netdeliver 下载指令 URI
任一条件不满足 → 保持 Check 状态,引擎持续推进,游戏侧设 120 秒硬超时,超时直接判 Bad
认证链路阶段:DNS 解析 → 认证握手 → 下载指令获取。任一环节与服务端通信异常则卡在 Check 直到超时
item5 Bad 后将阻断后续标题服配置下载流程,机台无法进入游戏画面,所以必须完整跑通 ALL.Net 认证流程才过
3.6 CHIME(AimeChecker)
引擎:Aime 网络客户端(AimeNetworkClient)
判定逻辑:
- 检测是否正在进行(引擎 state 满足运行中条件)
- 读取 CHIME 客户端的探活结果区首字:
- 等于 0 → OK
- 非 0(错误码)→ 运行中 / NG
游戏侧对应 Chime.Instance.IsDBAlive,即微信 AIME 服务的数据库存活探活
后续 WaitAime 阶段(Chime.StartDBAliveCheck)会再探一次,两处共用同一探活接口
3.7 Emoney(EmoneyChecker)国服废项
引擎:EmoneyNetworkClient
判定逻辑:结果区首字等于 0 → OK,非 0 → NG(与 AimeChecker 结构相同)。
国服:无配置目标,shouldRun 返回假,固定 NA 跳过。游戏界面无对应显示位(该位置复用为 TitleServer 探活,使用 OperationManager.IsAliveServer)
3.8 AimePay(AimePayChecker) 国服废项
引擎:AimePayCheckInSequencer
判定逻辑:结果区首字等于 0 → OK,非 0 → NG
国服:与 Emoney 相同,无配置目标,固定 NA 跳过,游戏页面无显示位
4. 结果回传与屏幕显示
4.1 传递链路
引擎结果(OK / NG) → item 结果区快照(引擎完成后拷入) → item 显示状态字(游戏程序每帧读取) → 网络可用性标志(IP / Hops / AllnetAuth 三项单独上报) → IPC(NamedPipe) → C# WaitNetWork 逐项翻译为屏幕状态三项可用性标志(IP、Hops、AllnetAuth)在 amdaemon app 侧单独维护,供后续流程判断网络就绪状态
4.2 游戏翻译规则
| 条件 | 显示 |
|---|---|
| 未忙且未完成 | NA |
| 忙且原生已判 NG | Bad 坏 |
| 忙且 item0(IP)超 15 秒 | Bad 坏 |
| 忙且 item5(Net 认证)超 120 秒 | Bad 坏 |
| 忙且其他 | Check 初始化中(闪烁) |
| 完成且通过 | Good 好(item3 额外显示跳数) |
| 完成且跳过 | NA |
| 完成且失败 | Bad 坏 |
超时兜底在 游戏 层(Stopwatch),错误语义在原生层
4.3 游戏显示侧说明
TestModePageNetwork.ItemEnum 共 8 位,对应关系:
- item0–5:直接读
Network.TestInfo,对应 IpAddress / Gateway / LocalDns / HopNum / LineType / AllnetAuth - item6(Aime):读
Chime.Instance.IsDBAlive,即 CHIME 微信 AIME 探活结果 - item7(TitleServer):读
OperationManager.IsAliveServer,与原生 item7 Emoney 无关(国服复用该槽位)
EnumEnum 中无 Emoney / AimePay 对应位
4.4 后续流程依赖
WaitNetWork 任一 Bad 或完成 → NetWorkReady → WaitAime(Chime.StartDBAliveCheck 再探一次)→ AimeReady → OperationManager.StartTest()(下载配置) → WaitTitleServer(下载成功且标题服存活) → Released:进入正常游戏调度item5(Net 认证)Bad 会在 WaitTitleServer 阶段阻断下载,其余项 Bad 不直接拦截流程但会影响后续功能
4.5 标题服务器(TitleServer)检查说明
title 不算严格意义上的原生网络自检。前文 9 项(item0-8)全部由 amdaemon 原生 am::network / am::networktest 体系执行,归属 WaitNetWork,原生侧没有 title 检查项:标题服务器不在 amdaemon 开机网络自检的枚举里,与 item7 Emoney 也无关
但开机流程确实会检查它。title 检查发生在网络自检之后、进入正常游戏调度之前,由 Unity 游戏 侧 OperationManager 驱动:
WaitNetWork 完成 → NetWorkReady → WaitAime(CHIME 再探一次)→ AimeReady → OperationManager.StartTest()(向 title 服务器下载配置) → WaitTitleServer(下载成功一次 + 标题服存活)→ Released- 判定条件:
WasDownloadSuccessOnce && IsAliveServer—— title 配置至少成功下载过一次,且标题服当前存活 - 谁在检查:Unity 游戏 侧(
OperationManager),不是原生自检框架 - 卡住表现:9 项网络自检全 Good 仍停在标题画面 → 大概率卡在
WaitTitleServer - 测试菜单:
TestModePageNetwork第 8 位显示 “TitleServer”,读的是OperationManager.IsAliveServer:复用原生 item7 的显示槽位,与原生自检无直接关系
所以对 title 的定位可以这样理解:严格意义上它是”配置下载 + 存活探活”,不属于原生开机初始化,但因为机台每次启动都会走到这一步、同样会被检查,广义上可以算作开机自检的一环。 它不在本文对 amd 原生 9 项网络自检的判定体系内,是网络自检通过之后的部分
5. 架构类名
5.1 networktest 检查器层
| item | 类名 | vftable 关键槽 |
|---|---|---|
| 0 | am::networktest::IpAddressChecker | shouldRun / update |
| 1 | am::networktest::GatewayChecker | shouldRun / update |
| 2 | am::networktest::DnsLanChecker | shouldRun / update |
| 3 | am::networktest::HopsChecker | shouldRun / update |
| 4 | am::networktest::LineTypeChecker | shouldRun / update |
| 5 | am::networktest::AllnetAuthChecker | shouldRun / update |
| 6 | am::networktest::AimeChecker | shouldRun / update |
| 7 | am::networktest::EmoneyChecker | shouldRun / update |
| 8 | am::networktest::AimePayChecker | shouldRun / update |
每项 vftable 含 6 个有效槽:dtor / shouldRun / 通用×2 / 辅助 / update。其中 shouldRun(slot1)决定是否运行,update(slot5)驱动引擎步进并写结果
5.2 am::network 引擎层
| 引擎类 | 对应功能 |
|---|---|
| am::network::IpAddressChecker | IP 地址有效性检测 |
| am::network::GatewayChecker(: GatewayPreChecker) | ICMP ping 网关 |
| am::network::DnsLanChecker | DNS 配置数量验证 |
| am::network::HopsCounter / NameResolver | 域名解析 + 路由跳数 |
| am::network::LocationRouterChecker | 线路类型(LAN/WAN)判定 |
| alw_auth | ALL.Net 认证全链路 |
| AimeNetworkClient | CHIME 客户端探活 |
| EmoneyNetworkClient | Emoney 探活(国服废项) |
| AimePayCheckInSequencer | AimePay 探活(国服废项) |
5.3 底层库分工
| 库 | 功能 |
|---|---|
| alw_auth | ALL.Net 认证、下载指令获取 |
| alw_network | 网络阶段初始化 |
| alw_dns | DNS 解析(alwDnsExecServer) |
| altr_icmp | ICMP / ping(网关与跳数底层) |
| alpb_stream_ssl | SSL 连接 |
| alib_pv2_lite(ALPB) | 开机自检状态机驱动 |
6. 依赖分类与排查
6.1 依赖分类
| item | 机台断网就挂 | 服务器没响应就挂 | 硬超时 |
|---|---|---|---|
| 0 IP 地址 | ✅ | — | 15s |
| 1 网关 | ✅ | — | — |
| 2 本地 DNS | ✅ | — | — |
| 3 跳数 | ✅ | ✅(域名不通) | — |
| 4 线路类型 | ✅ | — | — |
| 5 Net 认证 | ✅ | ✅ | 120s |
| 6 CHIME | ✅ | ✅ | — |
| 7 Emoney | — | — | 国服废项,NA |
| 8 AimePay | — | — | 国服废项,NA |
6.2 屏幕状态含义
- Check(初始化中 闪烁):引擎还在等待结果。长期 Check 多见于 item5 / item6,需确认服务端连通性
- Bad(坏):该项判定失败。item5 Bad 会阻断后续流程,其余项 Bad 不直接卡流程
- NA:该项不参与检测。item7 / item8 国服固定 NA,item0 在
ignore_unconnected模式下也会 NA
6.3 排查方向
item 0–4 内网失败:建议检查机台本身的网络配置:网线是否连通、DHCP 是否正常下发 IP 和 DNS、网关地址是否配置正确、线路是否接入局域网
item 5(Net 认证)失败或长期 初始化中:机台与 ALL.Net 认证服务器之间的连通性问题,建议检查机台是否连接到外网,以及服务器是否在线,可以用isMaiDown 查看服务器在线状态
item 6(CHIME)失败:CHIME 微信 AIME 服务连通性问题。检查 CHIME 服务端状态及机台到服务端的网络路径,建议使用刚才那个网站查看
item 7 / 8:国服废项
6.4 9 项判定标准总表
| item | 检查器 | 判定条件 | 通过 / 失败 |
|---|---|---|---|
| 0 | IpAddressChecker | 本机 IP 非 APIPA(169.254.x.x),属于有效网段 | OK / NG |
| 1 | GatewayChecker | ICMP ping 网关成功 | OK / NG |
| 2 | DnsLanChecker | 可查到的 DNS 数量满足配置要求 | OK / NG |
| 3 | HopsChecker | 目标域名 DNS 解析成功,ICMP 逐跳完成 | OK / NG |
| 4 | LineTypeChecker | 线路类型为 LAN | OK / NG |
| 5 | AllnetAuthChecker | 认证通过且下载指令就绪 | OK / 超时 Bad |
| 6 | AimeChecker | CHIME 探活结果正常 | OK / NG |
| 7 | EmoneyChecker | 国服废项,shouldRun 为 fake | NA |
| 8 | AimePayChecker | 国服废项,shouldRun 为 fake | NA |
附录
华立服务器状态监测: 华立服务器死了吗 - isMaiDown?
