Files
2026-07-10 10:24:29 +08:00

56 lines
2.2 KiB
C#

using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace XWorld.Server.Gateway
{
// 取本机内网主 IPv4,用于广播 advertise(仿 C++ XBroadcastServer.GetLocalIPAddress)。
// 优先选 Up、非 loopback、非隧道、带网关的网卡上的 IPv4;都没有则回退 127.0.0.1。
public static class LanIp
{
public static string Resolve()
{
// 1) 优先:有默认网关的活动网卡(最可能是真实内网口)
string withGateway = PickFromNics(requireGateway: true);
if (withGateway != null) return withGateway;
// 2) 退一步:任意 Up 的非 loopback/隧道网卡上的私有 IPv4
string anyUp = PickFromNics(requireGateway: false);
if (anyUp != null) return anyUp;
// 3) 兜底:DNS 解析本机名里的第一个 IPv4
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (addr.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(addr))
return addr.ToString();
}
return "127.0.0.1";
}
private static string PickFromNics(bool requireGateway)
{
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus != OperationalStatus.Up) continue;
if (nic.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
if (nic.NetworkInterfaceType == NetworkInterfaceType.Tunnel) continue;
IPInterfaceProperties props = nic.GetIPProperties();
if (requireGateway && !props.GatewayAddresses.Any(g => g.Address.AddressFamily == AddressFamily.InterNetwork))
continue;
foreach (UnicastIPAddressInformation ua in props.UnicastAddresses)
{
IPAddress ip = ua.Address;
if (ip.AddressFamily != AddressFamily.InterNetwork) continue;
if (IPAddress.IsLoopback(ip)) continue;
return ip.ToString();
}
}
return null;
}
}
}