Как получить IP всех хостов в локальной сети? - PullRequest
24 голосов
/ 28 октября 2010

Мне нужно перечислить IP-адреса всех подключенных хостов в моей локальной сети. Какой самый простой способ сделать это?

Ответы [ 7 ]

50 голосов
/ 28 октября 2010

Тебе придется сделать пинг. В пространстве имен System.Net есть класс Ping. Пример следует. Также это возможно, только если на ваших компьютерах не запущены брандмауэры. Если у них включен брандмауэр, невозможно определить эту информацию, кроме выполнения запросов SNMP на коммутаторах.

System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply rep = p.Send("192.168.1.1");
if (rep.Status == System.Net.NetworkInformation.IPStatus.Success)
{
    //host is active
}

Другая проблема заключается в определении размера вашей сети. В большинстве домашних ситуаций ваша сетевая маска будет 24 бита. Это означает, что он установлен на 255.255.255.0. Если ваш шлюз имеет адрес 192.168.1.1, это означает, что действительные адреса в вашей сети будут с 192.168.1.1 по 192.168.1.254. Вот вам IP Calculator , чтобы помочь. Вам придется пройтись по каждому адресу и пропинговать адрес с помощью класса Ping и проверить PingReply.

Если вы просто ищете информацию и не интересуетесь, как вы ее получаете, вы можете использовать NMap. Команда будет выглядеть следующим образом:

nmap -sP 192.168.1.0/24

EDIT:

Что касается скорости, то, поскольку вы находитесь в локальной сети, вы можете значительно сократить интервал времени ожидания, поскольку вашим машинам не требуется более 100 миллисекунд для ответа. Вы также можете использовать SendAsync, чтобы пинговать их всех параллельно. Следующая программа будет пинговать адрес 254 менее чем за полсекунды.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.NetworkInformation;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Net.Sockets;

namespace ConsoleApplication1
{
    class Program
    {
        static CountdownEvent countdown;
        static int upCount = 0;
        static object lockObj = new object();
        const bool resolveNames = true;

        static void Main(string[] args)
        {
            countdown = new CountdownEvent(1);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            string ipBase = "10.22.4.";
            for (int i = 1; i < 255; i++)
            {
                string ip = ipBase + i.ToString();

                Ping p = new Ping();
                p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
                countdown.AddCount();
                p.SendAsync(ip, 100, ip);
            }
            countdown.Signal();
            countdown.Wait();
            sw.Stop();
            TimeSpan span = new TimeSpan(sw.ElapsedTicks);
            Console.WriteLine("Took {0} milliseconds. {1} hosts active.", sw.ElapsedMilliseconds, upCount);
            Console.ReadLine();
        }

        static void p_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            string ip = (string)e.UserState;
            if (e.Reply != null && e.Reply.Status == IPStatus.Success)
            {
                if (resolveNames)
                {
                    string name;
                    try
                    {
                        IPHostEntry hostEntry = Dns.GetHostEntry(ip);
                        name = hostEntry.HostName;
                    }
                    catch (SocketException ex)
                    {
                        name = "?";
                    }
                    Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
                }
                else
                {
                    Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
                }
                lock(lockObj)
                {
                    upCount++;
                }
            }
            else if (e.Reply == null)
            {
                Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
            }
            countdown.Signal();
        }
    }
}

РЕДАКТИРОВАТЬ: После некоторого использования он сам изменил программу, чтобы вывести количество ответивших IP-адресов. Существует const bool, которое, если установлено в true, заставит программу разрешать имена хостов IP-адресов. Это значительно замедляет сканирование. (от полсекунды до 16 секунд) Также обнаружено, что если IP-адрес указан неверно (сам сделал опечатку), объект ответа может быть нулевым, поэтому я обработал это.

2 голосов
/ 28 октября 2010

Вам нужно будет создать диапазон адресов (например, 192.168.0.1 - 192.168.255.254) и пропинговать каждый из этих адресов. Если ответ получен, то этот хост активен.

Учебник по асинхронному пингу:

http://www.geekpedia.com/tutorial234_Asynchronous-Ping-using-Csharp.html

Однако некоторые новые операционные системы блокируют запросы ping (ICMP). Чтобы получить ответ, его необходимо отключить в брандмауэре на каждом компьютере.

0 голосов
/ 10 мая 2017
namespace WindowsFormsApplication1
{
    class WifiInformation
    {
        static CountdownEvent countdown;
        static int upCount = 0;
        static object lockObj = new object();
        const bool resolveNames = true;

        static void Main(string[] args)
        {
            string ipBase = getIPAddress();
            string[] ipParts = ipBase.Split('.');
            ipBase = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".";
            for (int i = 1; i < 255; i++)
            {
                string ip = ipBase + i.ToString();

                Ping p = new Ping();
                p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
                p.SendAsync(ip, 100, ip);
            }
            Console.ReadLine();
        }

        static void p_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            string ip = (string)e.UserState;
            if (e.Reply != null && e.Reply.Status == IPStatus.Success)
            {
                if (resolveNames)
                {
                    string name;
                    try
                    {
                        IPHostEntry hostEntry = Dns.GetHostEntry(ip);
                        name = hostEntry.HostName;
                    }
                    catch (SocketException ex)
                    {
                        name = "?";
                    }
                    Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
                }
                else
                {
                    Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
                }
                lock (lockObj)
                {
                    upCount++;
                }
            }
            else if (e.Reply == null)
            {
                Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
            }
        }

        public static string getIPAddress()
        {
            IPHostEntry host;
            string localIP = "";
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIP = ip.ToString();
                }
            }
            return localIP;
        }
    }
}
0 голосов
/ 22 марта 2017

Вы можете сделать все это в управляемом коде. Я делаю это, используя System.DirectoryServices и System.Net. По сути, я получаю имена локальных компьютеров от DirectoryServices (обрабатывая домены и рабочие группы по ходу работы), затем получаю IP-адреса каждого хоста из System.Net.Dns. Вот все, что упаковано в удобный класс ...

public class NetworkComputer {
    private string _domain;
    private string _name;
    private IPAddress[] _addresses = null;

    public string Domain { get { return _domain; } }
    public string Name { get { return _name; } }
    public IPAddress[] Addresses { get { return _addresses; } }

    private NetworkComputer(string domain, string name) {
        _domain = domain;
        _name = name;
        try { _addresses = Dns.GetHostAddresses(name); } catch { }
    }

    public static NetworkComputer[] GetLocalNetwork() {
        var list = new List<NetworkComputer>();
        using(var root = new DirectoryEntry("WinNT:")) {
            foreach(var _ in root.Children.OfType<DirectoryEntry>()) {
                switch(_.SchemaClassName) {
                    case "Computer":
                        list.Add(new NetworkComputer("", _.Name));
                        break;
                    case "Domain":
                        list.AddRange(_.Children.OfType<DirectoryEntry>().Where(__ => (__.SchemaClassName == "Computer")).Select(__ => new NetworkComputer(_.Name, __.Name)));
                        break;
                }
            }
        }
        return list.OrderBy(_ => _.Domain).ThenBy(_ => _.Name).ToArray();
    }
}

Тогда просто вызовите статический метод, чтобы получить массив компьютеров вашей локальной сети ...

var localComputers = NetworkComputer.GetLocalNetwork();
0 голосов
/ 13 ноября 2013

Ping на глобальный широковещательный IP-адрес (192.168.1.255)

Обычно мы получим ответ от всех хостов, подключенных к локальной сети. Или, если у вас есть какая-то конкретная сеть для локальной сети, отправьте ping-запрос на широковещательный идентификатор этой сети (т.е. последний IP-адрес в этом диапазоне).

Тогда вы можете узнать все IP-адреса, подключенные к хосту в локальной сети.

0 голосов
/ 28 октября 2010

Вместо того, чтобы устраивать дикую пинг-вечеринку, вы могли бы (я действительно точно не знаю!) Использовать NetBIOS (запросить имя netbios как-нибудь?) http://technet.microsoft.com/en-us/library/cc757216%28WS.10%29.aspx. Или почему бы не спросить свой DHCP-сервер?

0 голосов
/ 28 октября 2010

Вы можете пропинговать диапазон адресов и заметить, ответил ли хост.Конечно, это потребует от хоста ответа на пакеты ping.

...