web-dev-qa-db-ja.com

LAN内のすべてのホストのIPを取得する方法は?

LANに接続されているすべてのホストのIPアドレスをリストする必要があります。これを行う最も簡単な方法は何ですか?

24
Saint

Pingスイープを実行する必要があります。 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
}

もう1つの問題は、ネットワークの大きさを決定することです。ほとんどの家庭の状況では、ネットワークマスクは24ビットになります。これは、255.255.255.0に設定されることを意味します。ゲートウェイが192.168.1.1の場合、これはネットワーク上の有効なアドレスが192.168.1.1から192.168.1.254になることを意味します。 IP Calculator が役立ちます。各アドレスをループし、Pingクラスを使用してアドレスをpingし、PingReplyを確認する必要があります。

情報を探しているだけで、取得方法に関心がない場合は、NMapを使用できます。コマンドは次のようになります

nmap -sP 192.168.1.0/24

編集:

速度に関しては、ローカルネットワーク上にいるので、マシンが応答するのに100ミリ秒以上かかることはないため、タイムアウト間隔を大幅に短縮できます。また、SendAsyncを使用して、それらをすべて並行してpingすることもできます。次のプログラムは、254秒以内に254のアドレスにpingを実行します。

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のホスト名を解決します。ただし、これによりスキャンが大幅に遅くなります。 (0.5秒から16秒未満)また、IPアドレスが間違って指定された場合(自分で入力ミスをした場合)、応答オブジェクトがnullになる可能性があることもわかったため、それを処理しました。

50
Tim Coker

アドレス範囲(例:192.168.0.1-192.168.255.254)を構築し、それらのアドレスのそれぞれをpingする必要があります。応答が受信された場合、そのホストはアクティブです。

非同期Pingチュートリアル:

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

ただし、一部の新しいオペレーティングシステムでは、ping要求(ICMP)がブロックされます。応答を受信するには、各コンピューターのファイアウォールでこれを無効にする必要があります。

2
Evan Mulawski

アドレス範囲をpingして、ホストが応答するかどうかを確認できます。もちろん、これには、ホストがpingパケットに応答する必要があります。

0
Femaref

すべてマネージコードで実行できます。 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();
    }
}

次に、静的メソッドを呼び出して、LANコンピューターの配列を取得します...

var localComputers = NetworkComputer.GetLocalNetwork();
0
dynamichael