在一个网络中找到所有的IP地址

14

我正在尝试使用C#完成这项任务。我需要查找网络中所有活动的IP地址并在列表中显示它们。我可以ping网络中所有可用的(1...255)IP地址。但是我想让这个过程更快。


2
如果你想让它更快,同时ping所有IP地址:Ping.SendAsync - igrimpe
我刚刚运行了一个ping命令,像这样:for /l %n in (1,1,255) do ping 192.168.10.%x,使用process.start(),然后稍后读取ARP表条目,在网络中查找每个IP地址。但这非常慢。需要加速处理速度。 - Mehbube Arman
@MehbubeArman,网络中有多少个IP地址是可能的,而“足够快”是什么意思? - Mike Pennington
@MehbubeArman 我在我的回答中提供了一段可直接复制粘贴的代码。看看是否适用于你。 - user1693593
1
获取您的网络掩码并执行广播ping,例如 ping 192.168.0.255。但请记住,防火墙可能会决定忽略广播ping,或者完全忽略任何类型的ping。 - vladr
5个回答

17
这段代码可以在约1秒内扫描我的网络中的255个D类段。我用VB.net编写了它,并将其翻译成了C#(如果有任何错误,请见谅)。将其粘贴到控制台项目中并运行。根据需要进行修改。
注意:该代码适用于生产环境,特别是实例计数方面需要改进(尝试使用TaskFactoryBlockingCollection)。
如果结果不稳定,可以修改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

这个解决方案似乎在wait.SpinOnce()行上无限等待。 - codemann8
这是我目前找到的问题的最快解决方案。 - undefined

1
请参考此链接了解有关异步客户端套接字的更快速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());
        }
    }

引用自这篇微软文档。


感谢NewAmbition。但我正在寻找替代ping所有的方法。 - Mehbube Arman
1
为什么你在寻找替代方案?(即使在你的问题中也没有明确说明)- Pinging 可以让你看到 IP 是否在线。 - TheGeekZn
2
如果没有像域服务器/ DNS 服务器这样的中心参考点,主机注册就必须到达所有候选地址并查看是否有任何内容,ping 是执行此操作的方法。 - Alex K.

1

1
那似乎是他想要做的事情,而且应该也很快。 - Dr. Wummi
这个问题不太清楚,而且这个解决方案除了ping之外几乎没有提供更多的信息。 - Mike Pennington

0
    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
           }
        }  
    }

-3

实际上,我正在寻找一个涉及编程的解决方案。 - Mehbube Arman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接