一直在寻找一种奇怪的技巧来确定本地IP地址吗?然而,与之前的方法相比,它非常稳定?
[请查看最后对@caesay的回复]
这可能就是你要找的。
using (var s = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram,ProtocolType.Udp))
{
s.Bind( new System.Net.IPEndPoint(System.Net.IPAddress.Any,0));
s.Connect("google.com",0);
var ipaddr = s.LocalEndPoint as System.Net.IPEndPoint;
var addr = ipaddr.Address.ToString();
Console.WriteLine(addr);
}
那将创建一个UDP套接字,但不会在其上发送数据。然后,您可以查看套接字绑定到的本地接口和地址。您必须提供一个IP地址或主机名,我使用了google.com,这将由操作系统用于确定套接字将绑定到哪个接口以及使用此方法将找到哪个IP地址。对于99%以上的IP地址或主机名,您使用的接口+地址将用于默认路由上的流量。
虽然这有点难懂,但我认为它比上面的方法更可靠,人们使用PInvoke调用并扫描结构以查找接口的方法。
在我的3倍双接口系统中,我肯定发现它比使用启发式来尝试找出默认接口地址的NetworkInterface.GetAllNetworkInterfaces()结果要更健壮。
[更新/回应@caesay 2/6/2019]
@caesay在这里提出了一个很好的观点,因此我已经从使用UdpClient切换到Socket,并在Bind()之后显式调用了Socket.Connect()。我还审查了Connect()和LocalEndPoint的框架源代码,并且两者都立即调用其相应的Win32 OS系统调用,而不是推迟或懒惰地调用OS。 Win32 bind页面说“应用程序可以在调用bind后使用getsockname来了解已分配给套接字的地址和端口。如果Internet地址等于INADDR_ANY或in6addr_any,则getsockname不能保证在套接字连接之前提供地址”。现在明确解决了这个条件,并且在审查了框架源代码后,IP地址应始终在Connect()调用后可用。