私はこのC#を実行しようとしています。ネットワークでアクティブなすべてのIPアドレスを見つけて、リストに表示する必要があります。ネットワークで利用可能なすべての(1 ... 255)IPアドレスにpingを実行できます。しかし、私はこのプロセスをより速くしたいと思っています。
このコードは、ネットワークの255Dクラスセグメントを約1秒でスキャンします。私はそれをVB.netで作成し、C#に翻訳しました(エラーがある場合はお詫びします)。コンソールプロジェクトに貼り付けて実行します。必要に応じて変更します。
注:コードはnot本番環境に対応しており、特にインスタンスのカウントを改善する必要があります(代わりにTaskFactory
をBlockingCollection
で実装してみてください)。
結果的に不安定な場合は、ttl(存続時間)とタイムアウトを変更します。
コードを実行すると、次のような結果が得られます。
Pinging 255 destinations of D-class in 192.168.1.*
Active IP: 192.168.1.100
Active IP: 192.168.1.1
Finished in 00:00:00.7226731. Found 2 active IP-addresses.
C#コード:
using System.Net.NetworkInformation;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using System;
static class Module1
{
private static List<Ping> pingers = new List<Ping>();
private static int instances = 0;
private static object @lock = new object();
private static int result = 0;
private static int timeOut = 250;
private static int ttl = 5;
public static void Main()
{
string baseIP = "192.168.1.";
Console.WriteLine("Pinging 255 destinations of D-class in {0}*", baseIP);
CreatePingers(255);
PingOptions po = new PingOptions(ttl, true);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] data = enc.GetBytes("abababababababababababababababab");
SpinWait wait = new SpinWait();
int cnt = 1;
Stopwatch watch = Stopwatch.StartNew();
foreach (Ping p in pingers) {
lock (@lock) {
instances += 1;
}
p.SendAsync(string.Concat(baseIP, cnt.ToString()), timeOut, data, po);
cnt += 1;
}
while (instances > 0) {
wait.SpinOnce();
}
watch.Stop();
DestroyPingers();
Console.WriteLine("Finished in {0}. Found {1} active IP-addresses.", watch.Elapsed.ToString(), result);
Console.ReadKey();
}
public static void Ping_completed(object s, PingCompletedEventArgs e)
{
lock (@lock) {
instances -= 1;
}
if (e.Reply.Status == IPStatus.Success) {
Console.WriteLine(string.Concat("Active IP: ", e.Reply.Address.ToString()));
result += 1;
} else {
//Console.WriteLine(String.Concat("Non-active IP: ", e.Reply.Address.ToString()))
}
}
private static void CreatePingers(int cnt)
{
for (int i = 1; i <= cnt; i++) {
Ping p = new Ping();
p.PingCompleted += Ping_completed;
pingers.Add(p);
}
}
private static void DestroyPingers()
{
foreach (Ping p in pingers) {
p.PingCompleted -= Ping_completed;
p.Dispose();
}
pingers.Clear();
}
}
そしてVB.netコード:
Imports System.Net.NetworkInformation
Imports System.Threading
Module Module1
Private pingers As New List(Of Ping)
Private instances As Integer = 0
Private lock As New Object
Private result As Integer = 0
Private timeOut As Integer = 250
Private ttl As Integer = 5
Sub Main()
Dim baseIP As String = "192.168.1."
Dim classD As Integer = 1
Console.WriteLine("Pinging 255 destinations of D-class in {0}*", baseIP)
CreatePingers(255)
Dim po As New PingOptions(ttl, True)
Dim enc As New System.Text.ASCIIEncoding
Dim data As Byte() = enc.GetBytes("abababababababababababababababab")
Dim wait As New SpinWait
Dim cnt As Integer = 1
Dim watch As Stopwatch = Stopwatch.StartNew
For Each p As Ping In pingers
SyncLock lock
instances += 1
End SyncLock
p.SendAsync(String.Concat(baseIP, cnt.ToString()), timeOut, data, po)
cnt += 1
Next
Do While instances > 0
wait.SpinOnce()
Loop
watch.Stop()
DestroyPingers()
Console.WriteLine("Finished in {0}. Found {1} active IP-addresses.", watch.Elapsed.ToString(), result)
Console.ReadKey()
End Sub
Sub Ping_completed(s As Object, e As PingCompletedEventArgs)
SyncLock lock
instances -= 1
End SyncLock
If e.Reply.Status = IPStatus.Success Then
Console.WriteLine(String.Concat("Active IP: ", e.Reply.Address.ToString()))
result += 1
Else
'Console.WriteLine(String.Concat("Non-active IP: ", e.Reply.Address.ToString()))
End If
End Sub
Private Sub CreatePingers(cnt As Integer)
For i As Integer = 1 To cnt
Dim p As New Ping
AddHandler p.PingCompleted, AddressOf Ping_completed
pingers.Add(p)
Next
End Sub
Private Sub DestroyPingers()
For Each p As Ping In pingers
RemoveHandler p.PingCompleted, AddressOf Ping_completed
p.Dispose()
Next
pingers.Clear()
End Sub
End Module
Pingを高速化する方法については、非同期クライアントソケットに関する このリンク を参照してください。
編集:これを実現する方法の簡単なスニペット:
private static void StartClient() {
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "Host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve("Host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client,"This is a test<EOF>");
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
aRPルートを使用する場合は、すべてのアドレスに対してARP要求を送信し、少し待ってから、ホストのARPテーブルを調べるだけです。
これは役立つかもしれません
public static void NetPing()
{
Ping pingSender = new Ping();
foreach (string adr in stringAddressList)
{
IPAddress address = IPAddress.Parse(adr);
PingReply reply = pingSender.Send (address);
if (reply.Status == IPStatus.Success)
{
//Computer is active
}
else
{
//Computer is down
}
}
}