在本地网络中查找所有IP地址

10
我希望使用Java代码查找当前连接到的本地网络中所有设备的IP地址。 有用的实用程序 Advanced IP Scanner 能够在我的子网 192.168.178/24 中找到各种IP地址:

根据this的回答,我按照以下方式编写了我的代码:
import java.io.IOException;
import java.net.InetAddress;

public class IPScanner
{
    public static void checkHosts(String subnet) throws IOException
    {
        int timeout = 100;
        for (int i = 1; i < 255; i++)
        {
            String host = subnet + "." + i;
            if (InetAddress.getByName(host).isReachable(timeout))
            {
                System.out.println(host + " is reachable");
            }
        }
    }

    public static void main(String[] arguments) throws IOException
    {
        checkHosts("192.168.178");
    }
}

很不幸,这并没有输出任何结果,这意味着没有可达的IP地址。为什么?我的本地网络中存在设备,就像在“高级IP扫描仪”扫描中看到的那样。

5个回答

7

尝试增加超时时间。我使用了约5000毫秒,这对我有所帮助。 如果您不想等待5000毫秒 * 254 = 21分钟,还可以尝试使用并行ping地址的以下代码:

public static void getNetworkIPs() {
    final byte[] ip;
    try {
        ip = InetAddress.getLocalHost().getAddress();
    } catch (Exception e) {
        return;     // exit method, otherwise "ip might not have been initialized"
    }

    for(int i=1;i<=254;i++) {
        final int j = i;  // i as non-final variable cannot be referenced from inner class
        new Thread(new Runnable() {   // new thread for parallel execution
            public void run() {
                try {
                    ip[3] = (byte)j;
                    InetAddress address = InetAddress.getByAddress(ip);
                    String output = address.toString().substring(1);
                    if (address.isReachable(5000)) {
                        System.out.println(output + " is on the network");
                    } else {
                        System.out.println("Not Reachable: "+output);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();     // dont forget to start the thread
    }
}

对我来说完美地解决了问题。


你为什么要从1-254而不是0-255呢? - dwb
1
在我的网络设置中,0被用作默认网关,255用于广播,因此没有任何设备会连接到这些地址。 - The_Programmer

3

InetAddress.isReachable方法会使用ICMP ECHO REQUEST(如同ping命令)或请求端口7(echo端口):http://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html#isReachable%28int%29

高级IP扫描程序可能使用其他方式来发现主机(例如对radmin端口或http端口进行请求)。

一台主机可能处于启动状态,但不会响应ICMP ECHO REQUEST。

您尝试过从命令行ping某个主机吗?


主机可以被 ping 并回复。 - BullyWiiPlaza

1
也许可以尝试使用InetAddress.getByAddress(host)代替getByName,像这样:
    InetAddress localhost = InetAddress.getLocalHost();
    byte[] ip = localhost.getAddress();

    for (int i = 1; i <= 254; i++)
    {
        try
        {
            ip[3] = (byte)i; 
            InetAddress address = InetAddress.getByAddress(ip);

            if (address.isReachable(100))
            {
                output = address.toString().substring(1);
                System.out.print(output + " is on the network");
            }
    }

我取了这个自动检测代码示例 从这里

是你,VGMoose吗?干杯,伙计 ;) 然而,你的代码和应用程序无法找到我的任天堂 Wii 主机,所以你的网络扫描没有起作用,很抱歉。文件传输可以,但我需要手动输入我的 Wii 的 IP 地址。 - BullyWiiPlaza

0

Java 8 流解决方案

    IntStream.rangeClosed(1,254).mapToObj(num -> "192.168.0."+num).parallel()
            .filter((addr) -> {
                try {
                    return InetAddress.getByName(addr).isReachable(2000);
                } catch (IOException e) {
                    return false;
                }
            }
            ).forEach(System.out::println);

这是特定于/24网络的,但也有其他网络大小。 - Ron Maupin

0
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

public class NetworkTest {
    private static final List<String> availableDevices = new ArrayList<>();
    private static String myNetworkIp;
    private static String deviceIpv4;

    public static void main(String[] args) {
        getDeviceIpv4();
        getMyNetworkIp();

        Thread thread = createScanningThreads(20);

        while (thread.isAlive()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        printAvailableDevices();
    }

    public static void scanDevices(int start, int end) {
        for (int i = start; i <= end; ++i) {
            try {
                InetAddress addr = InetAddress.getByName(myNetworkIp + i);

                if (addr.isReachable(1000)) {
                    System.out.println("Available: " + addr.getHostAddress()); 
                    availableDevices.add(addr.getHostAddress());
                } else
                    System.out.println("Not available: " + addr.getHostAddress());

            } catch (IOException ignored) {

            }
        }
    }

    public static void getMyNetworkIp() {
        for (int i = deviceIpv4.length() - 1; i >= 0; --i) {
            if (deviceIpv4.charAt(i) == '.') {
                myNetworkIp = deviceIpv4.substring(0, i + 1);
                break;
            }
        }
    }

    public static void getDeviceIpv4() {
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            deviceIpv4 = localhost.getHostAddress();

            if (deviceIpv4.equals("127.0.0.1")) {
                System.out.println("This PC is not connected to any network!");
            }
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }

    public static Thread createScanningThreads(int threads) {
        Thread thread = null;

        for (int i = 0; i < threads; ++i) {
            int start = i * 256 / threads;
            int end = (i + 1) * 256 / threads - 1;
            System.out.println("Thread " + i + " will scan from " + start + " to " + end);

            thread = new Thread(() -> scanDevices(start, end));
            thread.start();
        }

        return thread;
    }

    public static void printAvailableDevices() {
        System.out.println("\nAll Connected devices(" + availableDevices.size() + "):");
        for (String availableDevice : availableDevices) System.out.println(availableDevice);
    }

}

这是一段使用线程扫描本地网络上所有可能的ipv4地址以更快地获取列表的代码。 所有ipv4地址的列表将存储在List中:
availableDevices

很抱歉,你可以通过在Java中实现线程池(通过ExecutorService)来更加优雅地完成这个任务。 - BullyWiiPlaza

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