4.4 KiB
4.4 KiB
局域网服务发现:组播叠加设计
日期:2026-07-06 状态:已批准(方案 A)
背景与问题
真机内网联调依赖 UDP 发现机制找到开发机上的网关/CDN 地址。当前客户端探测目标为:
255.255.255.255 + 127.0.0.1 + 各网卡子网定向广播 + 写死的开发机 IP 192.168.130.40。
定向广播默认不被路由器转发(RFC 2644,已实测不通),跨网段场景只能靠写死 IP 兜底——换机器/换网段就要改代码,不通用。
目标
- 新增组播探测路径,使发现请求有机会跨网段到达开发机(取决于路由器是否开启组播路由,当前网络环境未验证)。
- 纯增量改动:现有广播/loopback/写死 IP 路径全部保留,任何一条路通即发现成功;组播不通也不比现状差。
非目标
- 不移除写死 IP(实测组播跨网段可行后再删)。
- 不做探测 IP 可配置化(若组播实测失败,作为后续备选方案)。
- 不改发现协议本身(magic "XWDL"、端口 48923、编解码格式均不变)。
关键技术决策
| 决策 | 取值 | 理由 |
|---|---|---|
| 组播组地址 | 239.192.48.92 |
239.192.0.0/14 为组织本地范围(RFC 2365),专为跨子网管理域设计;239.255.0.0/16 是本地范围,路由器可能限制其跨网段 |
| 端口 | 48923(复用现有) |
服务端同一 socket 可同时收单播/广播/组播,零额外监听 |
| 客户端组播 TTL | 8 |
组播默认 TTL=1 出不了本网段;8 足够覆盖内网多级路由,又不至于扩散过远 |
| Android MulticastLock | 不需要 | 客户端只发组播、收单播回复;MulticastLock 只影响收组播 |
改动清单
1. 协议常量 XWorld.Framework.Protocol.DevDiscovery
新增:
public const string MulticastGroup = "239.192.48.92";
2. 服务端 Server\Gateway\DevDiscoveryResponder.cs
构造函数中,绑定 0.0.0.0:48923 后,枚举本机所有 Up 状态、非 Loopback 的 IPv4 网卡,对每块网卡执行:
_udp.JoinMulticastGroup(groupAddr, nicIPv4Addr);
- 默认
JoinMulticastGroup(group)只加入默认网卡,多网卡开发机(有线+无线/虚拟网卡)会漏收,故须逐网卡 join。 - 逐网卡 try/catch,任何一块失败不中断其余(与客户端
GetDirectedBroadcasts的容错风格一致)。 - 收包与回复逻辑零改动:组播查询的
RemoteEndPoint是发送方单播地址,现有单播回复天然可用。
3. 客户端热更层 Client\Assets\Script\xmain\MiniGame\DevServerDiscovery.cs
- socket 初始化后设置
MulticastTimeToLive = 8。 - 组播端点不加入
targets通用列表(避免只走默认路由网卡),而是在每轮重发中单独处理:逐 Up 状态 IPv4 网卡设置IP_MULTICAST_IF(SocketOptionName.MulticastInterface,值为网卡 IPv4 地址字节)后向239.192.48.92:48923发一次,逐网卡 try/catch。- 手机通常单网卡,此逻辑主要覆盖编辑器/PC 多网卡场景。
- 现有 targets(广播、loopback、定向广播、
DevExtraProbeIps)全部不动;DevExtraProbeIps注释更新:组播跨网段实测通过后可删。
4. 客户端底包 Client\Assets\Base\LocalCdnDiscovery.cs
与热更层同步:内联 MulticastGroup 常量(Base 程序集不能引用热更程序集,沿用现有"改协议时两边须同步"约定),发送逻辑同第 3 条。
错误处理
join / 设组播网卡 / 发送失败全部静默吞掉——发现机制是"多路齐发、谁通算谁",单路失败不影响整体,与现有代码风格一致。
测试
Server\Gateway.Tests\DevDiscoveryResponderTests.cs 新增一条:
- 客户端测试 socket 设置
MulticastLoopback = true、MulticastTimeToLive = 1,向239.192.48.92:48923发查询,断言收到合法回复(验证响应器 join 组播组 + 组播收包路径)。 - 现有单播/广播测试不动。
验收标准
- 服务端/客户端单元测试通过。
- 编辑器同机自测:发现日志中出现组播目标,发现成功。
- 真机同网段:发现成功(组播或广播任一路径)。
- 真机跨网段实测:若组播路径通 → 后续任务删除
DevExtraProbeIps写死 IP;若不通 → 保留写死 IP,评估"探测 IP 可配置化"方案。
风险
- 组播路由未验证:公司路由器可能未开 PIM/IGMP Proxy,组播出不了网段。缓解:纯增量设计,失败无损现状。
- 部分 Android WiFi 驱动丢组播发包:概率低(丢的主要是收方向),且广播路径仍在。