📝 UE 项目迁移银河麒麟(Linux)局域网会话搜索失败排查笔记
一、 问题现象
· 背景:UE 项目从 Windows 迁移至银河麒麟(Kylin)系统,常规打包成功。
· 表现:
· 主机端调用 CreateSession 创建房间成功。
· 客户端调用 FindSession 搜索不到任何房间(返回结果为空,UI 列表不显示)。
· 但是,客户端使用 Open IP:Port 直接连接主机是可以成功进入的。
· Windows 系统下此流程完全正常。
二、 排查过程
1. 服务端监听验证(正常)
· 在主机端抓包/查看日志,确认 CreateSession 后底层网络驱动工作正常。
· 终端日志显示:IpNetDriver listening on port 7777。
· 使用 netstat / ss 命令验证,确认 7777 端口(UDP/TCP)已处于监听状态,绑定地址为 0.0.0.0。
2. 客户端报错定位(核心线索)
· 客户端运行游戏点击"搜索房间"后,终端输出关键报错:
LogTemp: Warning: Failed to send discovery broadcast SE_ENETUNREACH
· 同时伴随蓝图报错:Attempted to access index 0 from array 'Temp struct Variable' of length 0(因搜索结果为空导致)。
3. 环境确认(多网卡干扰)
· 执行 ip addr 查看客户端和主机端的网络环境。
· 发现系统存在多个网络接口:物理网卡 enp5s0(IP: 192.168.1.x),以及大量 Docker 虚拟网桥(docker0、br-56...)和虚拟网卡(veth...)。
· 判断:Linux 系统内核在发送全局广播(255.255.255.255)时,因多网卡存在导致路由表混乱,内核不知道从哪个网卡发出去,从而直接拒绝发包。
4. 网络连通性测试(证明物理链路畅通)
· 停止 Docker 服务(systemctl stop docker),重新搜索,问题依旧。
· 手动使用 nc 命令测试发定向子网广播:
echo "test" | nc -u -b 192.168.1.255 7777
· 在主机端 tcpdump 成功抓到这个包,证明物理网络链路、网段、交换机配置完全没问题。
· 踩坑提示:用 nc 给 UE 发送纯文本包会让 UE 底层的 FBitReader 解析崩溃(SetOverflowed),因为 UE 期望的是特定的二进制握手协议。这反证了 UE 原生广播无法发出,但链路通畅。
5. 锁定内核心结(抓包对比)
· 在客户端指定物理网卡抓包:sudo tcpdump -i enp5s0 -n udp port 7777。
· 结果:毫无反应。客户端执行 FindSession 时,系统底层根本没有把包发到物理网卡上(被内核吞了或路由到了虚拟网卡)。
三、 最终解决方案与原因剖析
🎯 解决方案(临时修复)
在主机端和客户端都执行以下路由命令(假设真实物理网卡名为 enp5s0):
```bash
sudo ip route add 255.255.255.255 dev enp5s0
```
执行完毕后,两端重新运行游戏,客户端成功搜到主机创建的会话!
🔍 为什么必须"两端都加"?
-
客户端(发包端):添加路由后,强制内核将发往 255.255.255.255 的全局广播包从物理网卡 enp5s0 扔出去,解决了 SE_ENETUNREACH 报错。
-
主机端(收包与回包端):主机收到探测包后,UE 引擎在回包时,底层逻辑依然会尝试使用带有全局广播地址的 Socket 或路由逻辑。如果主机端不加这条路由,它的响应包也会被多网卡路由表迷惑,丢进 docker0 或虚拟网桥的黑洞中。客户端收不到响应,UI 依然显示 0 个房间。
四、 后续优化建议(重要!)
1. 临时方案的重启失效问题
ip route add 命令是临时生效的,系统重启后会丢失。
· 建议:编写开机自启脚本,或者在网卡配置文件中添加静态路由,确保每次开机自动执行。
2. 正式发布项目的代码级根治(强烈推荐)
要求玩家或客户敲 Linux 命令是不现实的,必须在 UE C++ 代码层面绕过这个跨平台深坑。推荐以下三种方案:
· 方案 A(最推荐):绑定物理网卡
在创建 Socket 时,通过 FUdpSocketBuilder 的 .BoundToDevice(TEXT("enp5s0")) 强制绑定到真实物理网卡,不再让内核自己去猜。
· 方案 B:改用定向子网广播
放弃引擎默认的 255.255.255.255,在 C++ 代码中手动计算出当前网段的定向广播地址(如 192.168.1.255),并强制以此为目标发送。
· 方案 C:手写单播扫描(终极兜底)
完全绕开 FindSession 的广播机制。在 C++ 中写一个循环,从 192.168.1.1 遍历到 192.168.1.254,向每个 IP 的 7777 端口发送自定义探测包。主机端收到后回复信息,客户端将回包的主机加入 UI 列表,点击时走现有的 Open IP 逻辑。
核心工具:ip addr, ip route, tcpdump, nc, ss, strace, iptables