如何使用C#获取IP地址的物理(MAC)地址?

12

我希望从C#中做出等效于以下操作:

arp -a |findstr 192.168.1.254

或者,答案可以调用SendARP函数并获取结果。

这将使我的应用程序能够执行一些需要MAC地址的其他处理。

4个回答

28

SendARP P/Invoke 的代码如下:

[DllImport("iphlpapi.dll", ExactSpelling=true)]
public static extern int SendARP( int destIp, int srcIP, byte[] macAddr, ref uint physicalAddrLen );

PInvoke.NET有一个相关例子:

IPAddress dst = IPAddress.Parse("192.168.2.1"); // the destination IP address

byte[] macAddr = new byte[6];
uint macAddrLen = (uint)macAddr.Length;

if (SendARP(BitConverter.ToInt32(dst.GetAddressBytes(), 0), 0, macAddr, ref macAddrLen) != 0)
     throw new InvalidOperationException("SendARP failed.");

string[] str = new string[(int)macAddrLen];
for (int i=0; i<macAddrLen; i++)
     str[i] = macAddr[i].ToString("x2");

Console.WriteLine(string.Join(":", str));

3
以下是我在使用Wireshark测试Windows XP时发现的关于此答案需要了解的事情:1)如果IP/MAC地址对已经在ARP缓存中,则ARP请求包将不会在网络上发送,但SendARP仍将返回其缓存中具有的(潜在过期的)mac地址。2)如果只使用一个线程,则此方法可能非常缓慢。使用单个线程循环遍历完整子网IP地址(例如192.168.1.x)需要250秒以上(每个IP地址1秒钟)。将其变成大规模多线程只需不到一秒钟即可处理所有250+个地址。 - Pretzel

4

这是我的解决方案。

public static class MacResolver
{
    /// <summary>
    /// Convert a string into Int32  
    /// </summary>
    [DllImport("Ws2_32.dll")]
    private static extern Int32 inet_addr(string ip);

    /// <summary>
    /// The main funtion 
    /// </summary> 
    [DllImport("Iphlpapi.dll")]
    private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 len);

    /// <summary>
    /// Returns the MACAddress by a string.
    /// </summary>
    public static Int64 GetRemoteMAC(string remoteIP)
    {   
        Int32 ldest = inet_addr(remoteIP);

        try
        {
            Int64 macinfo = 0;           
            Int32 len = 6;           

            int res = SendARP(ldest, 0, ref macinfo, ref len);

            return macinfo;    
        }
        catch (Exception e)
        {
            return 0;
        }
    }

    /// <summary>
    /// Format a long/Int64 into string.   
    /// </summary>
    public static string FormatMac(this Int64 mac, char separator)
    {
        if (mac <= 0)
            return "00-00-00-00-00-00";

        char[] oldmac = Convert.ToString(mac, 16).PadLeft(12, '0').ToCharArray();

        System.Text.StringBuilder newMac = new System.Text.StringBuilder(17);

        if (oldmac.Length < 12)
            return "00-00-00-00-00-00";

        newMac.Append(oldmac[10]);
        newMac.Append(oldmac[11]);
        newMac.Append(separator);
        newMac.Append(oldmac[8]);
        newMac.Append(oldmac[9]);
        newMac.Append(separator);
        newMac.Append(oldmac[6]);
        newMac.Append(oldmac[7]);
        newMac.Append(separator);
        newMac.Append(oldmac[4]);
        newMac.Append(oldmac[5]);
        newMac.Append(separator);
        newMac.Append(oldmac[2]);
        newMac.Append(oldmac[3]);
        newMac.Append(separator);
        newMac.Append(oldmac[0]);
        newMac.Append(oldmac[1]);

        return newMac.ToString();
    }
}

只有在使用IP地址时,此函数才返回有效的Mac地址,而在使用主机名时,Mac地址是错误的。 - Gopi

1

钩入WMI子系统。一些VBScript代码可以帮助您朝着正确的方向前进,在这里


1

查找您自己的:

添加对System.Management的引用

ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");

ManagementObjectCollection mcCol = mc.GetInstances();

foreach (ManagementObject mcObj in mcCol)
{
  Console.WriteLine(mcObj["Caption"].ToString());
  Console.WriteLine(mcObj["MacAddress"].ToString());
}

不确定如何找到另一个设备的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接