【问题标题】:How do I use ResolveIpNetEntry2 in C#如何在 C# 中使用 ResolveIpNetEntry2
【发布时间】:2012-03-04 10:17:18
【问题描述】:

我正在尝试在 C# 中检索 IPv6 主机的 MAC 地址。我发现这个question 提到使用 ResolveIpNetEntry2。经过一番谷歌搜索并参考了 MSDN,我还没有找到如何从 C# 调用此函数的示例。此功能在 pinvoke.net 上也未列出。

有人有如何从 C# 调用 ResolveIpNetEntry2 的示例吗?

【问题讨论】:

    标签: c# network-programming ipv6


    【解决方案1】:

    这是一个显示所需结构以及如何调用 ResolveIpNetEntry2 的类:

    class ResolveMac
    {
        private const short AF_INET6 = 23;
    
        #region Structs for ResolveIpNetEntry2
    
        struct MIB_IPNET_ROW2
        {
            public SOCKADDR_INET Address;
            public uint InterfaceIndex;
            public ulong InterfaceLuid;
    
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] PhysicalAddress;
    
            public uint PhysicalAddressLength;
            public NL_NEIGHBOR_STATE State;
            public byte Flags;
            public uint LastReachable;
        }
    
        private struct SOCKADDR_INET
        {
            public SOCKADDR_IN6 Ipv6;
        }
    
        private struct SOCKADDR_IN6
        {
            public short sin6_family;
            public ushort sin6_port;
            public uint sin6_flowinfo;
            public in6_addr sin6_addr;
            public uint sin6_scope_id;
        }
    
        struct in6_addr
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public byte[] Byte;
        }
    
        #endregion
    
        private enum NL_NEIGHBOR_STATE
        {
            NlnsUnreachable,
            NlnsIncomplete,
            NlnsProbe,
            NlnsDelay,
            NlnsStale,
            NlnsReachable,
            NlnsPermanent,
            NlnsMaximum
        }
    
        [DllImport("Iphlpapi.dll")]
        private static extern int ResolveIpNetEntry2(ref MIB_IPNET_ROW2 Row,
            ref SOCKADDR_INET SourceAddress);
    
        public static byte[] GetMacFromIPv6Address(IPAddress ipv6Address)
        {
            if (ipv6Address.AddressFamily != 
                System.Net.Sockets.AddressFamily.InterNetworkV6)
                throw new ArgumentException(
                    "The IPAddress provided was not an IPv6 address.");
    
            //set up target address
            MIB_IPNET_ROW2 row2 = new MIB_IPNET_ROW2();
            row2.PhysicalAddress = new byte[32];
            row2.State = NL_NEIGHBOR_STATE.NlnsReachable;
            row2.Address.Ipv6.sin6_addr.Byte = new byte[16];
            row2.Address.Ipv6.sin6_family = AF_INET6;
            row2.Address.Ipv6.sin6_flowinfo = 0;
            row2.Address.Ipv6.sin6_port = 0;
            row2.Address.Ipv6.sin6_scope_id = Convert.ToUInt32(ipv6Address.ScopeId);
    
            byte[] ipv6AddressBytes = ipv6Address.GetAddressBytes();
            System.Buffer.BlockCopy(ipv6AddressBytes, 0, 
                row2.Address.Ipv6.sin6_addr.Byte, 0, ipv6AddressBytes.Length);
    
            //get this machine's local IPv6 address
            SOCKADDR_INET sock = new SOCKADDR_INET();
            sock.Ipv6.sin6_family = AF_INET6;
            sock.Ipv6.sin6_flowinfo = 0;
            sock.Ipv6.sin6_port = 0;
            sock.Ipv6.sin6_addr.Byte = new byte[16];
    
            IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (IPAddress address in addresses)
            {
                if (address.AddressFamily == 
                    System.Net.Sockets.AddressFamily.InterNetworkV6)
                {
                    sock.Ipv6.sin6_addr.Byte = address.GetAddressBytes();
                    break;
                }
            }
    
            foreach (NetworkInterface netInterface in 
                NetworkInterface.GetAllNetworkInterfaces())
            {
                if (netInterface.OperationalStatus == OperationalStatus.Up)
                {
                    row2.InterfaceIndex = (uint)clsNetworkStats.GetInterfaceIndex(
                        netInterface.Description);
                    break;
                }
            }
    
            int result = ResolveIpNetEntry2(ref row2, ref sock);
    
            if (result != 0)
                throw new ApplicationException(
                    "The call to ResolveIpNetEntry2 failed; error number: " + 
                    result.ToString());
    
            byte[] macAddress = new byte[6];
            System.Buffer.BlockCopy(row2.PhysicalAddress, 0, macAddress, 0, 6);
    
            return macAddress;
        }
    
    }
    

    基本上,只需 ping 目标主机,并将返回的地址提供给此函数。

    类 clsNetworkStats 用于确定应使用的 InterfaceIndex。我找到了这个代码示例here 并稍作修改。

    internal class clsNetworkStats
    {
        // Fields
        private const long ERROR_SUCCESS = 0L;
        private ArrayList m_Adapters;
        private const long MAX_INTERFACE_NAME_LEN = 0x100L;
        private const long MAXLEN_IFDESCR = 0x100L;
        private const long MAXLEN_PHYSADDR = 8L;
    
        // Methods
        public clsNetworkStats()
            : this(true)
        {
        }
        public clsNetworkStats(bool IgnoreLoopBack)
        {
            int lRetSize = 0;
            MIB_IFROW ifrow = new MIB_IFROW();
            byte[] buff = new byte[1];
            byte val = 0;
            long ret = GetIfTable(ref val, ref lRetSize, 0);
            buff = new byte[lRetSize];
            ret = GetIfTable(ref buff[0], ref lRetSize, 0);
            int lRows = buff[0];
            this.m_Adapters = new ArrayList(lRows);
            byte len = (byte)lRows;
            for (byte i = 1; i <= len; i++)
            {
                ifrow = new MIB_IFROW();
                ifrow.dwIndex = Convert.ToUInt32(i);
                ret = GetIfEntry(ref ifrow);
                IFROW_HELPER ifhelp = this.PrivToPub(ifrow);
                if (IgnoreLoopBack)
                {
                    if (ifhelp.Description.IndexOf("Loopback") < 0)
                    {
                        this.m_Adapters.Add(ifhelp);
                    }
                }
                else
                {
                    this.m_Adapters.Add(ifhelp);
                }
            }
        }
    
        public IFROW_HELPER GetAdapter(int index)
        {
            return (IFROW_HELPER)this.m_Adapters[index];
        }
    
        public int Count
        {
            get
            {
                return this.m_Adapters.Count;
            }
        }
    
        [DllImport("iphlpapi")]
        private static extern int GetIfEntry(ref MIB_IFROW pIfRow);
        [DllImport("iphlpapi")]
        private static extern int GetIfTable(ref byte pIfRowTable, ref int pdwSize, int bOrder);
        //[DebuggerStepThrough]
        private IFROW_HELPER PrivToPub(MIB_IFROW pri)
        {
            IFROW_HELPER ifhelp = new IFROW_HELPER();
            ifhelp.Name = pri.wszName.Trim();
            ifhelp.Index = Convert.ToInt32(pri.dwIndex);
            ifhelp.Type = Convert.ToInt32(pri.dwType);
            ifhelp.Mtu = Convert.ToInt32(pri.dwMtu);
            ifhelp.Speed = Convert.ToInt32(pri.dwSpeed);
            ifhelp.PhysAddrLen = Convert.ToInt32(pri.dwPhysAddrLen);
            ifhelp.PhysAddr = Encoding.ASCII.GetString(pri.bPhysAddr);
            ifhelp.AdminStatus = Convert.ToInt32(pri.dwAdminStatus);
            ifhelp.OperStatus = Convert.ToInt32(pri.dwOperStatus);
            ifhelp.LastChange = Convert.ToInt32(pri.dwLastChange);
            ifhelp.InOctets = pri.dwInOctets; //Convert.ToInt32(pri.dwInOctets);
            ifhelp.InUcastPkts = Convert.ToInt32(pri.dwInUcastPkts);
            ifhelp.InNUcastPkts = Convert.ToInt32(pri.dwInNUcastPkts);
            ifhelp.InDiscards = Convert.ToInt32(pri.dwInDiscards);
            ifhelp.InErrors = Convert.ToInt32(pri.dwInErrors);
            ifhelp.InUnknownProtos = Convert.ToInt32(pri.dwInUnknownProtos);
            ifhelp.OutOctets = pri.dwOutOctets;//Convert.ToInt32(pri.dwOutOctets);
            ifhelp.OutUcastPkts = Convert.ToInt32(pri.dwOutUcastPkts);
            ifhelp.OutNUcastPkts = Convert.ToInt32(pri.dwOutNUcastPkts);
            ifhelp.OutDiscards = Convert.ToInt32(pri.dwOutDiscards);
            ifhelp.OutErrors = Convert.ToInt32(pri.dwOutErrors);
            ifhelp.OutQLen = Convert.ToInt32(pri.dwOutQLen);
            ifhelp.Description = Encoding.ASCII.GetString(pri.bDescr, 0, Convert.ToInt32(pri.dwDescrLen));
            ifhelp.InMegs = this.ToMegs((long)ifhelp.InOctets);
            ifhelp.OutMegs = this.ToMegs((long)ifhelp.OutOctets);
            return ifhelp;
        }
    
        [DebuggerStepThrough]
        private string ToMegs(long lSize)
        {
            string sDenominator = " B";
            if (lSize > 0x3e8L)
            {
                sDenominator = " KB";
                lSize = (long)Math.Round((double)(((double)lSize) / 1000.0));
            }
            else if (lSize <= 0x3e8L)
            {
                sDenominator = " B";
                //            lSize = lSize;
            }
    
            return lSize.ToString("###,###") + sDenominator;
            //            (Strings.Format(lSize, "###,###0") + sDenominator);
        }
    
        // Nested Types
        [StructLayout(LayoutKind.Sequential)]
        public struct IFROW_HELPER
        {
            public string Name;
            public int Index;
            public int Type;
            public int Mtu;
            public int Speed;
            public int PhysAddrLen;
            public string PhysAddr;
            public int AdminStatus;
            public int OperStatus;
            public int LastChange;
            public uint InOctets;   //changed
            public int InUcastPkts;
            public int InNUcastPkts;
            public int InDiscards;
            public int InErrors;
            public int InUnknownProtos;
            public uint OutOctets;  //changed
            public int OutUcastPkts;
            public int OutNUcastPkts;
            public int OutDiscards;
            public int OutErrors;
            public int OutQLen;
            public string Description;
            public string InMegs;
            public string OutMegs;
        }
    
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct MIB_IFROW
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x100)]
            public string wszName;
            public uint dwIndex;
            public uint dwType;
            public uint dwMtu;
            public uint dwSpeed;
            public uint dwPhysAddrLen;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] bPhysAddr;
            public uint dwAdminStatus;
            public uint dwOperStatus;
            public uint dwLastChange;
            public uint dwInOctets;
            public uint dwInUcastPkts;
            public uint dwInNUcastPkts;
            public uint dwInDiscards;
            public uint dwInErrors;
            public uint dwInUnknownProtos;
            public uint dwOutOctets;
            public uint dwOutUcastPkts;
            public uint dwOutNUcastPkts;
            public uint dwOutDiscards;
            public uint dwOutErrors;
            public uint dwOutQLen;
            public uint dwDescrLen;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
            public byte[] bDescr;
        }
    
        public static int GetInterfaceIndex(string description)
        {
            int val = 0;
    
            clsNetworkStats stats = new clsNetworkStats();
            for (int index = 0; index < stats.Count; index++)
            {
                string desc = stats.GetAdapter(index).Description;
                if (desc == description + "\0")
                {
                    val = stats.GetAdapter(index).Index;
                    break;
                }
            }
    
            return val;
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多