C#中不使用Dns.GetHostEntry()获取IPHostEntry值的替代方案
替代Dns.GetHostEntry()的可行方案
根据你的代码需求,核心是获取目标主机的IP地址列表,以下是两种可行的替代方案:
方案一:使用Dns.GetHostAddresses()构造IPHostEntry
Dns.GetHostAddresses()方法直接返回目标主机的IP地址数组,你可以用它手动构造IPHostEntry对象,完全满足原有代码的需求:
String urlSvr = m.Groups[2].Value.ToLower(); IPAddress[] addresses = Dns.GetHostAddresses(machine); IPHostEntry serverEntry = new IPHostEntry { AddressList = addresses, HostName = machine // 若需要真实主机名,可结合其他逻辑获取,或直接使用传入的machine值 }; if (urlSvr == machine || machine.StartsWith(urlSvr) || urlSvr == serverEntry.AddressList[0].ToString()) { _log.Debug(String.Format(CultureInfo.InvariantCulture, "Machine match {0}, {1}", machine, urlSvr)); }
这个方案最简洁,和原方法核心逻辑对齐,完全覆盖现有代码的使用场景。
方案二:P/Invoke调用底层GetAddrInfo函数(Windows平台)
如果需要更底层的DNS解析控制,可以直接调用Windows系统的GetAddrInfoAPI,手动解析并构造IPHostEntry:
using System; using System.Net; using System.Runtime.InteropServices; using System.Globalization; // 定义P/Invoke相关结构体和函数 [StructLayout(LayoutKind.Sequential)] internal struct addrinfo { public int ai_flags; public int ai_family; public int ai_socktype; public int ai_protocol; public IntPtr ai_addrlen; public IntPtr ai_canonname; public IntPtr ai_addr; public IntPtr ai_next; } [StructLayout(LayoutKind.Sequential)] internal struct sockaddr_in { public short sin_family; public ushort sin_port; public uint sin_addr; public byte[] sin_zero; } [DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern int GetAddrInfo(string pNodeName, string pServiceName, IntPtr pHints, out IntPtr ppResult); [DllImport("ws2_32.dll")] internal static extern void FreeAddrInfo(IntPtr pAddrInfo); // 自定义解析方法 private static IPHostEntry GetHostEntryAlternative(string machine) { IntPtr result = IntPtr.Zero; try { int error = GetAddrInfo(machine, null, IntPtr.Zero, out result); if (error != 0) throw new System.ComponentModel.Win32Exception(error); var addresses = new System.Collections.Generic.List<IPAddress>(); string hostName = machine; IntPtr ptr = result; while (ptr != IntPtr.Zero) { addrinfo info = Marshal.PtrToStructure<addrinfo>(ptr); if (info.ai_canonname != IntPtr.Zero) hostName = Marshal.PtrToStringUni(info.ai_canonname); if (info.ai_addr != IntPtr.Zero && info.ai_family == 2) // 解析IPv4 { sockaddr_in sockAddr = Marshal.PtrToStructure<sockaddr_in>(info.ai_addr); byte[] ipBytes = BitConverter.GetBytes(sockAddr.sin_addr); Array.Reverse(ipBytes); addresses.Add(new IPAddress(ipBytes)); } else if (info.ai_addr != IntPtr.Zero && info.ai_family == 23) // 如需支持IPv6,可补充此处逻辑 { // IPv6解析代码 } ptr = info.ai_next; } return new IPHostEntry { AddressList = addresses.ToArray(), HostName = hostName }; } finally { if (result != IntPtr.Zero) FreeAddrInfo(result); } } // 使用示例 String urlSvr = m.Groups[2].Value.ToLower(); IPHostEntry serverEntry = GetHostEntryAlternative(machine); if (urlSvr == machine || machine.StartsWith(urlSvr) || urlSvr == serverEntry.AddressList[0].ToString()) { _log.Debug(String.Format(CultureInfo.InvariantCulture, "Machine match {0}, {1}", machine, urlSvr)); }
这个方案适合需要自定义DNS解析逻辑的场景,但仅适用于Windows平台,代码复杂度较高。
内容的提问来源于stack exchange,提问作者zia
相关产品推荐
相关产品推荐

