LANに接続されているすべてのホストのIPアドレスをリストする必要があります。これを行う最も簡単な方法は何ですか?
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になる可能性があることもわかったため、それを処理しました。
アドレス範囲(例:192.168.0.1-192.168.255.254)を構築し、それらのアドレスのそれぞれをpingする必要があります。応答が受信された場合、そのホストはアクティブです。
非同期Pingチュートリアル:
http://www.geekpedia.com/tutorial234_Asynchronous-Ping-using-Csharp.html
ただし、一部の新しいオペレーティングシステムでは、ping要求(ICMP)がブロックされます。応答を受信するには、各コンピューターのファイアウォールでこれを無効にする必要があります。
アドレス範囲をpingして、ホストが応答するかどうかを確認できます。もちろん、これには、ホストがpingパケットに応答する必要があります。
すべてマネージコードで実行できます。 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();