gpt4 book ai didi

c# - 如何在 C# 中使用 ResolveIpNetEntry2

转载 作者:太空狗 更新时间:2023-10-29 23:40:56 30 4
gpt4 key购买 nike

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

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

最佳答案

这是一个显示所需结构以及如何调用 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;
}
}

关于c# - 如何在 C# 中使用 ResolveIpNetEntry2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9253300/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com