I need to get the list of MAC addresses of all computers on the LAN. How can i do this? I think that you can get this list from the DHCP server, but I can not figure out how to do it.
1 answer
For receiving we use the code:
// Получить мой IP-адрес компьютера Console.WriteLine("My IP : {0}", GetIPAddress()); // Получить мой MAC-адрес компьютера Console.WriteLine("My MAC: {0}", GetMacAddress()); // Получить все устройства в сети Dictionary<IPAddress, PhysicalAddress> all = GetAllDevicesOnLAN(); foreach (KeyValuePair<IPAddress, PhysicalAddress> kvp in all) { Console.WriteLine("IP : {0}\n MAC {1}", kvp.Key, kvp.Value); } For his work the following structure and methods:
/// <summary> /// MIB_IPNETROW cтруктура возвращаемая GetIpNetTable /// НЕ ИЗМЕНЯЙТЕ ЭТУ СТРУКТУРУ. /// </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 Внешний метод /// </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> /// Коды ошибок GetIpNetTable возвращает, что мы распознаем /// </summary> const int ERROR_INSUFFICIENT_BUFFER = 122; /// <summary> /// Получить IP-адреса и MAC-адреса всех известных устройств в локальной сети. /// </summary> /// <remarks> /// 1) Эта таблица не обновляется часто - выбор из неё может занять некоторое время /// , чтобы выявить, что устройство пропало из сети или новое устройство было подключено. /// 2) Фильтрует не локальные устройства, если они найдены - это многоадресная рассылка /// и могут быть исключены по диапазону IP-адресов. /// </remarks> /// <returns></returns> private static Dictionary<IPAddress, PhysicalAddress> GetAllDevicesOnLAN() { Dictionary<IPAddress, PhysicalAddress> all = new Dictionary<IPAddress, PhysicalAddress>(); // Добавляем этот компьютер в список ... all.Add(GetIPAddress(), GetMacAddress()); int spaceForNetTable = 0; // Получаем необходимое пространство // Мы делаем это, запрашивая таблицу, но не указывая никакого пространства вообще. // Возвращаемое значение скажет нам, сколько нам действительно нужно. GetIpNetTable(IntPtr.Zero, ref spaceForNetTable, false); // Распределяем пространство // Мы используем блок try-finally для обеспечения выполнения. IntPtr rawTable = IntPtr.Zero; try { rawTable = Marshal.AllocCoTaskMem(spaceForNetTable); // Получаем фактические данные int errorCode = GetIpNetTable(rawTable, ref spaceForNetTable, false); if (errorCode != 0) { // Сбой по какой-то причине - здесь больше ничего нельзя сделать. throw new Exception(string.Format( "Unable to retrieve network table. Error code {0}", errorCode)); } // Получаем количество строк int rowsCount = Marshal.ReadInt32(rawTable); IntPtr currentBuffer = new IntPtr(rawTable.ToInt64() + Marshal.SizeOf(typeof(Int32))); // Конвертируем необработанную таблицу в отдельные записи 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)); } // Определяем список фиктивных записей (мы можем их отбросить) 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 { // Освобождаем память Marshal.FreeCoTaskMem(rawTable); } return all; } /// <summary> /// Получает IP-адрес текущего ПК /// </summary> /// <returns></returns> private 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> /// Получает MAC-адрес текущего ПК. /// </summary> /// <returns></returns> private static PhysicalAddress GetMacAddress() { foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { // Учитывть только сетевые интерфейсы Ethernet if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet && nic.OperationalStatus == OperationalStatus.Up) { return nic.GetPhysicalAddress(); } } return null; } /// <summary> /// Метод возвращает "истина", если указанный IP-адрес является адресом многоадресной рассылки /// </summary> /// <param name="ip"></param> /// <returns></returns> private 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; } |