web-dev-qa-db-fra.com

Comment obtenir l'IP de tous les hôtes du LAN?

Je dois répertorier les adresses IP de tous les hôtes connectés dans mon réseau local. Quelle est la manière la plus simple de procéder?

28
Saint

Vous devrez effectuer un balayage ping. Il y a une classe Ping dans l'espace de noms System.Net. Un exemple suit. Cela n'est également possible que si vos ordinateurs n'ont pas de pare-feu en cours d'exécution. S'ils ont un pare-feu activé, il n'y a aucun moyen de déterminer ces informations à moins d'effectuer des requêtes SNMP sur vos commutateurs.

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
}

L'autre problème consiste à déterminer la taille de votre réseau. Dans la plupart des situations domestiques, votre masque de réseau sera de 24 bits. Cela signifie que sa valeur est 255.255.255.0. Si votre passerelle est 192.168.1.1, cela signifie que les adresses valides sur votre réseau seront de 192.168.1.1 à 192.168.1.254. Voici une calculatrice IP pour vous aider. Vous devrez parcourir chaque adresse et envoyer une requête ping à l'adresse à l'aide de la classe Ping et vérifier la réponse Ping.

Si vous recherchez simplement les informations et que vous ne souhaitez pas obtenir ces informations, vous pouvez utiliser NMap. La commande serait la suivante

nmap -sP 192.168.1.0/24

ÉDITER:

En ce qui concerne la vitesse, puisque vous êtes sur un réseau local, vous pouvez réduire considérablement le délai d'expiration car vos machines ne devraient pas prendre plus de 100 millisecondes pour répondre. Vous pouvez également utiliser SendAsync pour les envoyer tous en parallèle. Le programme suivant enverra une requête ping à 254 adresses en moins d'une demi-seconde.

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();
        }
    }
}

EDIT: Après une certaine utilisation de moi-même, j'ai modifié le programme pour afficher le nombre d'IP qui ont répondu. Il y a un const bool qui, s'il est défini sur true, entraînera la résolution des noms d'hôte des adresses IP par le programme. Cependant, cela ralentit considérablement l'analyse. (moins d'une demi-seconde à 16 secondes) A ​​également constaté que si l'adresse IP est incorrectement spécifiée (fait une faute de frappe moi-même), l'objet de réponse peut être nul, donc j'ai géré cela.

50
Tim Coker

Vous devez créer une plage d'adresses (par exemple, 192.168.0.1 - 192.168.255.254) et envoyer une requête ping à chacune de ces adresses. Si une réponse est reçue, cet hôte est actif.

Tutoriel Ping asynchrone:

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

Cependant, certains systèmes d'exploitation plus récents bloquent les requêtes ping (ICMP). Cela devrait être désactivé dans le pare-feu de chaque ordinateur pour que vous receviez une réponse.

2
Evan Mulawski

Vous pouvez cingler la plage d'adresses et noter si un hôte répond. Bien sûr, cela nécessitera que l'hôte réponde aux paquets ping.

0
Femaref

Vous pouvez tout faire en code managé. Je le fais en utilisant System.DirectoryServices et System.Net. Fondamentalement, j'obtiens les noms des ordinateurs locaux à partir de DirectoryServices (gestion des domaines et des groupes de travail au fur et à mesure), puis j'obtiens les adresses IP de chaque hôte à partir de System.Net.Dns. Voici tout emballé dans une classe pratique ...

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();
    }
}

Ensuite, appelez simplement la méthode statique pour obtenir un tableau de vos ordinateurs LAN ...

var localComputers = NetworkComputer.GetLocalNetwork();
0
dynamichael