MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как считать подключенные IP адреса с локальной сети?"
Answer 843385
Зависит от того, что такое "подключенные IP адреса с локальной сети". Если имеются в виду адреса компьютеров в текущем домене / рабочей группе NetBIOS, их можно получить с помощью функции NetServerEnum:
using System; using System.Text; using System.Linq; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Net; using System.Windows.Forms; namespace WindowsFormsTest1 { public partial class Form1 : Form { /*Source: https://stackoverflow.com/questions/20512242/find-all-computers-on-network-using-netserverenum */ [DllImport("Netapi32", CharSet = CharSet.Auto, SetLastError = true)] public static extern int NetServerEnum( string serverName, int dwLevel, ref IntPtr pBuf, int dwPrefMaxLen, out int dwEntriesRead, out int dwTotalEntries, int dwServerType, string domain, out int dwResumeHandle ); [DllImport("Netapi32", SetLastError = true)] public static extern int NetApiBufferFree(IntPtr pBuf); [StructLayout(LayoutKind.Sequential)] public struct ServerInfo100 { internal int sv100_platform_id; [MarshalAs(UnmanagedType.LPWStr)] internal string sv100_name; } public static List<string> GetNetworkComputers(string domain = null) { List<string> networkComputers = new List<string>(); const int MAX_PREFERRED_LENGTH = -1; int SV_TYPE_WORKSTATION = 1; int SV_TYPE_SERVER = 2; IntPtr buffer = IntPtr.Zero; IntPtr tmpBuffer = IntPtr.Zero; int entriesRead; int totalEntries; int resHandle; int sizeofInfo = Marshal.SizeOf(typeof(ServerInfo100)); string elem; try { int ret = NetServerEnum(null, 100, ref buffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, SV_TYPE_WORKSTATION | SV_TYPE_SERVER, domain, out resHandle); if (ret == 0) { for (int i = 0; i < totalEntries; i++) { tmpBuffer = new IntPtr((long)buffer + (i * sizeofInfo)); ServerInfo100 svrInfo = (ServerInfo100) Marshal.PtrToStructure(tmpBuffer, typeof(ServerInfo100)); elem = svrInfo.sv100_name; try { IPAddress[] ips = Dns.GetHostAddresses(svrInfo.sv100_name); IPAddress ip = ips.First(); if (ip != null) elem += ": " + ip.ToString(); } catch (Exception ex) { elem += " " + ex.Message; } networkComputers.Add(elem); } } } finally { NetApiBufferFree(buffer); } return networkComputers; } public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { var list = GetNetworkComputers(); textBox1.Text = ""; foreach (var s in list) { textBox1.Text += s + Environment.NewLine; } } } }
IP-адреса для компьютеров, с которыми недавно взаимодействовал текущий компьютер, можно получить из ARP-кэша, как в этом ответе.
Если подразумеваются все адреса в пределах какой-либо IP-подсети, можно сделать это только сканированием всех адресов. Для этого нужно сначала определить условие существование адреса: это может быть наличие для него имени в обратном DNS, прохождение пинга, наличие на каком-либо порту сервера, принимающего входящие соединения и т.п. (выберите то условие, которое имеет смысл в вашем окружении). Например, определим метод для проверки наличия информации по IP-адресу в обратном DNS:
//метод проверки существования IP-адреса static async Task<bool> CheckIp(IPAddress x) { var task = Task.Run<bool>(() => { string res = ""; try { var entry = Dns.GetHostEntry(x); //получаем информацию из обратного DNS if (entry.HostName != null && entry.HostName != "") res = (entry.HostName); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); res = ""; } return res != ""; }); return await task; }
Тогда просканировать все адреса в IPv4-cети можно как-то так:
using System; using System.Text; using System.Linq; using System.Threading.Tasks; using System.Collections.Generic; using System.Net; using System.Windows.Forms; namespace WindowsFormsTest1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } static void IncrementIp(ref uint x) { byte[] bytes = BitConverter.GetBytes(x); uint y = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] },0); y++; bytes = BitConverter.GetBytes(y); x = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0); } static int IpCompare(uint x, uint y) { if (x == y) return 0; byte[] bytes = BitConverter.GetBytes(x); uint xx = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0); bytes = BitConverter.GetBytes(y); uint yy = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0); if (xx < yy) return -1; else return 1; } private async void button1_Click(object sender, EventArgs e) { IPAddress net = IPAddress.Parse("192.168.100.0"); //адрес подсети IPAddress mask = IPAddress.Parse("255.255.255.0"); //маска подсети uint x1 = (uint)net.Address; //начальный адрес подсети uint x2 = (uint)(~mask.Address | net.Address); //конечный адрес подсети textBox1.Text = ""; //сканирование IP-адресов IncrementIp(ref x1); for(uint i = x1; IpCompare(i,x2)<0; IncrementIp(ref i)) { IPAddress ip = new IPAddress((long)i); bool res = await CheckIp(ip); if (res) { textBox1.Text += ip.ToString() + Environment.NewLine; } } } } }
Определить время подключения и отключения компьютеров можно только периодическим сканированием с сохранением результатов и сравнением их с предыдущими сканированиями.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.