如何使用 Java 获取连接在同一网络(子网)中的 IP 列表

Posted

技术标签:

【中文标题】如何使用 Java 获取连接在同一网络(子网)中的 IP 列表【英文标题】:How to get a list of IP connected in same network (subnet) using Java 【发布时间】:2011-03-21 17:24:39 【问题描述】:

如何获取使用 Java 连接到同一子网的设备的 IP 地址列表?

【问题讨论】:

“局域网中连接的 IP”到底是什么意思? 你给出的所有帖子都有点耗时,需要 8 分钟才能搜索连接到 LAN 的 50 台 PC,我想要最快的方法来获取连接到 LAN 的 IP 地址,以便我可以显示它在 JCOMBOBOX 上请任何人给我最快的方法, 【参考方案1】:

当您网络上的主机响应 ICMP 包 (ping) (>JDK 5) 时,这应该可以工作:

public void checkHosts(String subnet)
   int timeout=1000;
   for (int i=1;i<255;i++)
       String host=subnet + "." + i;
       if (InetAddress.getByName(host).isReachable(timeout))
           System.out.println(host + " is reachable");
       
   

像这样调用子网(192.168.0.1-254)的方法:

checkHosts("192.168.0");

没有测试它,但应该像这样工作。显然这里只检查ip地址最后一个字节中的254个主机...

检查:

http://download-llnw.oracle.com/javase/6/docs/api/java/net/InetAddress.html#isReachable%28int%29 http://blog.taragana.com/index.php/archive/how-to-do-icmp-ping-in-java-jdk-15-and-above/

希望有所帮助

【讨论】:

提供了很好的解决方案 'LAN' = 'class D IP subnet'。 感谢您的解释。 操作系统肯定已经有了这些信息,有没有办法检索它,因为这个实现可能需要一段时间...... 我一直在寻找的伟大而优雅的解决方案。 这个过程需要多快?【参考方案2】:

要列出 LAN 中连接的主机,您需要 ping 子网上所有可用的 IP 地址。但是 ping 消息可能会受到防火墙的限制,因此更安全的方法可以是为 LAN 的 IP 地址范围内的每个 IP 地址打开一个套接字。

【讨论】:

套接字?到哪个港口?以及如何确保防火墙不会阻止它? +1 用于提供基本信息以 ping 子网中的所有 ip。 局域网可以被分割成多个子网。 但是ping和获取所有本地wifi地址太慢了。【参考方案3】:

从 Java 1.5 开始,java.net.InetAddress 中有一个类似 ping 的方法: 公共布尔 isReachable(int 超时)。您可以使用它来遍历子网中的所有 IP 地址...java-doc

【讨论】:

【参考方案4】:

如果您的意思是连接到网络的所有主机的列表,我认为唯一能保证工作的方法是逐步检查 IP 地址列表并 ping 它们。

也就是说,如果您正在寻找更具体的内容,您可以查找一些内容(例如 RMI 的注册表 (LocateRegistry.getRegistry(host, port).list())。

另外,如果您只想要给定主机拥有的所有 IP 地址,请查看NetworkInterface.getNetworkInterfaces()

【讨论】:

不。 LocateRegistry.getRegistry 不进行任何通信。它只是构造一个注册表存根。 应该调用 list() 。无论如何,这有点没有实际意义——我忘记了默认情况下 RMI 只允许对象向本地注册表注册,因此您仍然需要检查每个主机上的注册表。您需要使用 Bonjour 之类的东西来进行服务发现 - 这是我的观点。【参考方案5】:

我看到了另一个答案。它非常好。但与实际情况相比,它的速度相当慢,不应该在这样的场景中使用。

这就是我要说的。

当我使用答案https://***.com/a/3345981/14911094

代码:

import java.net.InetAddress;
public class Main 
    public static void main(String[] args)  throws Exception
        long initialT = System.currentTimeMillis();
        checkHosts("192.168.0");
        long finalT = System.currentTimeMillis();
        System.out.println("Scan Completed taking " + (finalT - initialT) + " miliseconds approximately!");
    
    
    public static void checkHosts(String subnet) throws Exception
   int timeout=1000;
   for (int i=1;i<255;i++)
       String host=subnet + "." + i;
       if (InetAddress.getByName(host).isReachable(timeout))
           System.out.println(host + " is reachable");
       
   


输出:

sudo java Main
[sudo] password for jaysmito: 
192.168.0.1 is reachable
192.168.0.2 is reachable
192.168.0.3 is reachable
192.168.0.4 is reachable
192.168.0.10 is reachable
Scan Completed taking 250151 miliseconds approximately!

这很慢,但我尝试使用这个概念制作更好的版本:

代码:

import java.net.*;
import java.io.*;
import java.util.*;

class AddressFinderLevel4 extends Thread
  private String addmask;
  private Stack<String> stack;
  private int start, end;

  public AddressFinderLevel4(String addmask, Stack stack, int start, int end)
    this.addmask = addmask;
    this.stack = stack;
    this.start = start;
    this.end = end;
  

  @Override
  public void run()
    try
        int timeout=1000;
      for(int i = start; i <= end; i++)
        String host=addmask + "." + i;
            if (InetAddress.getByName(host).isReachable(timeout))
                stack.push(host);
            
      
    catch(Exception ex)

    
  


class AddressFinderLevel3 extends Thread
  private String addmask;
  private Stack<String> stack;
  private int start, end;
  private int packSize;

  public AddressFinderLevel3(String addmask, Stack stack, int packSize, int start, int end)
    this.addmask = addmask;
    this.stack = stack;
    this.start = start;
    this.end = end;
    this.packSize = packSize;
  

  @Override
  public void run()
    try
      for(int i = start; i <= end; i++)
        int j = 1;
        String host =  addmask + "." + i;
        while(j<=255)
          AddressFinderLevel4 addressFinderLevel4 = new AddressFinderLevel4(host, stack, j, j+packSize+5);
          addressFinderLevel4.start();
          j = j + packSize;
        
      
    catch(Exception ex)
      ex.printStackTrace();
    
  




public class Main 
    public static void main(String[] args) throws Exception 
      System.out.println("Starting search!");
      Stack data = find();
      Thread.sleep(1000);
      System.out.println("Data found in 1000 miliseconds");
      data.forEach(System.out::println);
      Thread.sleep(10000);
      System.out.println("Data found in 10000 miliseconds");
      data.forEach(System.out::println);
      Thread.sleep(25000);
      System.out.println("Data found in 25000 miliseconds");
      data.forEach(System.out::println);
    

    public static Stack find()
      Stack<String> stack = new Stack<String>();
      AddressFinderLevel3 finder = new AddressFinderLevel3("192.168", stack, 10, 0, 255);
      finder.start();
      return stack;
    

输出:

sudo java Main
Starting search!
Data found in 1000 miliseconds
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
Data found in 10000 miliseconds
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.99.152
192.168.0.10
192.168.102.227
192.168.99.161
Data found in 25000 miliseconds
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.99.152
192.168.0.10
192.168.102.227
192.168.99.161

如您所见,这可以在更短的时间内扫描更多的 IP。

我也为所有可能的 ips 完成了它,但这会占用太多内存并且不需要!

这是一个更快的解决方案,因此性能应该更好!

【讨论】:

如果我想获取主机名和 MAC 地址怎么办?【参考方案6】:

显示 LAN 上的活动地址

public static void main(String[] args) 
    try 
        Enumeration nis = NetworkInterface.getNetworkInterfaces();
        while(nis.hasMoreElements())
        
            NetworkInterface ni = (NetworkInterface) nis.nextElement();
            Enumeration ias = ni.getInetAddresses();
            while (ias.hasMoreElements())
            
                InetAddress ia = (InetAddress) ias.nextElement();
                System.out.println(ia.getHostAddress());
            

        
     catch (SocketException ex) 
        Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
    

输出

127.0.0.1
0:0:0:0:0:0:0:1
172.128.1.102

【讨论】:

这不适用于所提出的问题 - 它只会返回绑定到网络设备的地址,即 localhost 在各种网络上的地址。 是的,同意@danielunderwood【参考方案7】:

这些都不适合我,因为我创建了服务器并且它没有响应这些 ping。因此,我创建了一种机制,使服务器回复 ping,并对子网中的所有地址使用暴力检查方法。

PS:写这个是因为创建自己的服务器的人可能需要这个。

【讨论】:

【参考方案8】:

这里的一个问题是“LAN”和“connected”这两个术语在 TCP/IP 中都没有意义。如果您的 LAN 与 D 类子网精确对应,那么在 D 类子网中的所有主机上调用 isReachable() 的建议技术可能会起作用。

你最好看看 SAMBA,它可以通过 SMB 询问 LAN 成员,所以至少你会使用一种对 LAN 具有相同含义的技术。

【讨论】:

以上是关于如何使用 Java 获取连接在同一网络(子网)中的 IP 列表的主要内容,如果未能解决你的问题,请参考以下文章

如何使用java获取本地系统的子网掩码?

如何判断2个ip是不是是在同一网段

java如何获取子网掩码?

如何获取局域网内主机信息-连接网络帐号\密码

如何判断两个IP是不是在同一个网段内

Case11-适配器作用/创建子网的目的