如何获取本地网络中的IP地址及其具有设备MAC的http端口

时间:2014-01-11 18:13:28

标签: c# .net ip

我的设备MAC连接到我的本地网络:00408CBEEAE5。

如何在C#中查询该设备的IP地址?

1 个答案:

答案 0 :(得分:1)

您可以尝试使用IpHlpApi.dll中的方法GetIpNetTable

Here您可以在.Net和PInvoke中找到如何使用此方法的示例代码。它会返回Dictionary<IPAddress, PhysicalAddress>,但您可以根据IPAddress更新它,只返回一个PhysicalAddress

关于第二个问题,是的,您需要迭代该主机上的所有已打开端口,并检查它们中是否有任何一个返回正确的Http响应,这意味着WebServer正在侦听此端口。但它不会那么快。而像Outpost Firewall这样的防火墙可能会认为它是一种攻击并阻止你的IP一段时间。

<强> UPDATE1

从样本中复制代码

public class IPHelper
{
    /// <summary>
    /// MIB_IPNETROW structure returned by GetIpNetTable
    /// DO NOT MODIFY THIS STRUCTURE.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    struct MIB_IPNETROW
    {
        [MarshalAs(UnmanagedType.U4)]
        public int dwIndex;
        [MarshalAs(UnmanagedType.U4)]
        public int dwPhysAddrLen;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac0;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac1;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac2;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac3;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac4;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac5;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac6;
        [MarshalAs(UnmanagedType.U1)]
        public byte mac7;
        [MarshalAs(UnmanagedType.U4)]
        public int dwAddr;
        [MarshalAs(UnmanagedType.U4)]
        public int dwType;
    }

    /// <summary>
    /// GetIpNetTable external method
    /// </summary>
    /// <param name="pIpNetTable"></param>
    /// <param name="pdwSize"></param>
    /// <param name="bOrder"></param>
    /// <returns></returns>
    [DllImport("IpHlpApi.dll")]
    [return: MarshalAs(UnmanagedType.U4)]
    static extern int GetIpNetTable(IntPtr pIpNetTable,
          [MarshalAs(UnmanagedType.U4)] ref int pdwSize, bool bOrder);

    /// <summary>
    /// Error codes GetIpNetTable returns that we recognise
    /// </summary>
    const int ERROR_INSUFFICIENT_BUFFER = 122;
    /// <summary>
    /// Get the IP and MAC addresses of all known devices on the LAN
    /// </summary>
    /// <remarks>
    /// 1) This table is not updated often - it can take some human-scale time 
    ///    to notice that a device has dropped off the network, or a new device
    ///    has connected.
    /// 2) This discards non-local devices if they are found - these are multicast
    ///    and can be discarded by IP address range.
    /// </remarks>
    /// <returns></returns>
    public static Dictionary<IPAddress, PhysicalAddress> GetAllDevicesOnLAN()
    {
        Dictionary<IPAddress, PhysicalAddress> all = new Dictionary<IPAddress, PhysicalAddress>();
        // Add this PC to the list...
        all.Add(GetIPAddress(), GetMacAddress());
        int spaceForNetTable = 0;
        // Get the space needed
        // We do that by requesting the table, but not giving any space at all.
        // The return value will tell us how much we actually need.
        GetIpNetTable(IntPtr.Zero, ref spaceForNetTable, false);
        // Allocate the space
        // We use a try-finally block to ensure release.
        IntPtr rawTable = IntPtr.Zero;
        try
        {
            rawTable = Marshal.AllocCoTaskMem(spaceForNetTable);
            // Get the actual data
            int errorCode = GetIpNetTable(rawTable, ref spaceForNetTable, false);
            if (errorCode != 0)
            {
                // Failed for some reason - can do no more here.
                throw new Exception(string.Format(
                  "Unable to retrieve network table. Error code {0}", errorCode));
            }
            // Get the rows count
            int rowsCount = Marshal.ReadInt32(rawTable);
            IntPtr currentBuffer = new IntPtr(rawTable.ToInt64() + Marshal.SizeOf(typeof(Int32)));
            // Convert the raw table to individual entries
            MIB_IPNETROW[] rows = new MIB_IPNETROW[rowsCount];
            for (int index = 0; index < rowsCount; index++)
            {
                rows[index] = (MIB_IPNETROW)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() +
                                            (index * Marshal.SizeOf(typeof(MIB_IPNETROW)))
                                           ),
                                            typeof(MIB_IPNETROW));
            }
            // Define the dummy entries list (we can discard these)
            PhysicalAddress virtualMAC = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 });
            PhysicalAddress broadcastMAC = new PhysicalAddress(new byte[] { 255, 255, 255, 255, 255, 255 });
            foreach (MIB_IPNETROW row in rows)
            {
                IPAddress ip = new IPAddress(BitConverter.GetBytes(row.dwAddr));
                byte[] rawMAC = new byte[] { row.mac0, row.mac1, row.mac2, row.mac3, row.mac4, row.mac5 };
                PhysicalAddress pa = new PhysicalAddress(rawMAC);
                if (!pa.Equals(virtualMAC) && !pa.Equals(broadcastMAC) && !IsMulticast(ip))
                {
                    //Console.WriteLine("IP: {0}\t\tMAC: {1}", ip.ToString(), pa.ToString());
                    if (!all.ContainsKey(ip))
                    {
                        all.Add(ip, pa);
                    }
                }
            }
        }
        finally
        {
            // Release the memory.
            Marshal.FreeCoTaskMem(rawTable);
        }
        return all;
    }

    /// <summary>
    /// Gets the IP address of the current PC
    /// </summary>
    /// <returns></returns>
    public static IPAddress GetIPAddress()
    {
        String strHostName = Dns.GetHostName();
        IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
        IPAddress[] addr = ipEntry.AddressList;
        foreach (IPAddress ip in addr)
        {
            if (!ip.IsIPv6LinkLocal)
            {
                return (ip);
            }
        }
        return addr.Length > 0 ? addr[0] : null;
    }

    /// <summary>
    /// Gets the MAC address of the current PC.
    /// </summary>
    /// <returns></returns>
    public static PhysicalAddress GetMacAddress()
    {
        foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            // Only consider Ethernet network interfaces
            if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                nic.OperationalStatus == OperationalStatus.Up)
            {
                return nic.GetPhysicalAddress();
            }
        }
        return null;
    }

    /// <summary>
    /// Returns true if the specified IP address is a multicast address
    /// </summary>
    /// <param name="ip"></param>
    /// <returns></returns>
    public static bool IsMulticast(IPAddress ip)
    {
        bool result = true;
        if (!ip.IsIPv6Multicast)
        {
            byte highIP = ip.GetAddressBytes()[0];
            if (highIP < 224 || highIP > 239)
            {
                result = false;
            }
        }
        return result;
    } 

    public static IPAddress GetIPAddress(PhysicalAddress physicalAddress)
    {
        var localIPs = GetAllDevicesOnLAN();
        foreach (var pair in localIPs)
        {
            if (pair.Value.Equals(physicalAddress))
                return pair.Key;
        }

        return null;
    }
}

使用示例:

class Program
{
    static void Main(string[] args)
    {// Get my PC IP address
        Console.WriteLine("My IP : {0}", IPHelper.GetIPAddress());
        // Get My PC MAC address
        Console.WriteLine("My MAC: {0}", IPHelper.GetMacAddress());
        // Get all devices on network
        Dictionary<IPAddress, PhysicalAddress> all = IPHelper.GetAllDevicesOnLAN();

        foreach (KeyValuePair<IPAddress, PhysicalAddress> kvp in all)
        {
            Console.WriteLine("IP : {0}\n MAC {1}", kvp.Key, kvp.Value);
        }

        PhysicalAddress ph = PhysicalAddress.Parse("485B39C25E67");

        var ip = IPHelper.GetIPAddress(ph);
        Console.WriteLine("IP is {0}", ip);

    }
}