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; } } }