56 lines
2.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|