【问题标题】:find ip address of all devices on network with particular port number open查找网络上所有设备的 IP 地址,并打开特定的端口号
【发布时间】:2017-03-04 11:17:38
【问题描述】:
 Socket socket = new Socket();

try {
Process process = Runtime.getRuntime().exec("arp -i en0 -a -n");
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

while (reader.ready()) {
    String ip = reader.readLine();
    ip = ip.substring(3, ip.indexOf(')'));

    try {
        socket.connect(new InetSocketAddress(ip, 1234), 1000);
        System.out.println("Found socket!");
    } catch (ConnectException | SocketTimeoutException ignored) {

    }
}

if (socket == null) {
    System.err.println("Could not find socket.");
}
} catch (Exception e) {
e.printStackTrace();
}

我在 stackoverflow bt 上找到了此代码,它适用于 mac,我需要为 windows OS 找到替代方案。 在 Windows 上它给出了一个例外

【问题讨论】:

  • 你有没有做过一些研究并被困在某个地方?请在此处提问之前分享错误消息,以及您为尝试诊断问题所采取的调试步骤。
  • 我试过 bt 没弄明白
  • java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:-4 at java.lang.String.substring(String.java:1967) at javaapplication21.JavaApplication21.main(JavaApplication21.java:66)

标签: java windows networking ip port


【解决方案1】:

首先,我不相信 Windows 中使用的 ARP (Address Resolution Protocol) 有 -i 参数。有一个 -n 参数,但它是 -N 而 N 是大写的。显然 ARP 命令行是错误的,您应该使用 Windows 命令提示符窗口自行检查。您只需在命令提示符窗口中输入 arp 即可查看 ARP 的所有可用参数。

要检索 ARP 表,您只需要提供:“arp -a”,但您会收到比您讨价还价的更多的东西,并由您自行解析所需的 IP 地址连接到我认为是动态 IP 的连接设备。以下是来自 Windows 10 机器的 ARP 表示例:

Interface: 192.168.0.25 --- 0x2
  Internet Address      Physical Address      Type
  192.168.0.69          25-ad-42-bb-bd-65     dynamic
  192.168.0.254         b8-29-34-f9-27-65     dynamic
  192.168.0.255         ff-ff-ff-ff-ff-ff     static
  224.0.0.2             01-00-5e-00-00-02     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  224.0.0.253           01-00-5e-00-00-fd     static
  239.255.255.250       01-00-5e-7f-ff-fa     static
  239.255.255.253       01-00-5e-7f-ff-fd     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static

如前所述,我相信您想要的是动态 IP 地址,但无论您想要什么,都取决于您解析和清理数据。当您解析出所需的数据时,最好将其放入 List 数组中。下面我提供了一个可以在您的 Windows 计算机上运行的小型可运行文件:

package networkdevices;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;


public class NetworkDevices {
    private static int port = 1234;

    public static void main(String[] args) {
        getNetworkDevices();
    }

    private static void getNetworkDevices(){
        Socket socket = new Socket();

        try {
            Process process = Runtime.getRuntime().exec("arp -a"); 
            process.waitFor();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String ip = null;
            List<String> ipList = new ArrayList<>(); // List<> Array to hold dynamic IP Addresses
            while ((ip = reader.readLine()) != null) {
                ip = ip.trim();     // Trim the data
                if (!ip.equals("")) { 
                    if (!ip.equals("")) {
                        // Remove all the unwanted spaces between data provided by 
                        // the ARP Table when it is generated.
                        while (ip.contains("  ")) { ip = ip.trim().replace("  ", " "); }
                        // Split each data line into a String Array for processing
                        String[] dataArray = ip.split(" ");
                        // For console output display only...
                        if (dataArray[0].toLowerCase().startsWith("interface:")) {
                            System.out.println("Locating Devices Connected To: " + dataArray[1]);
                        }
                        // If the data line contains the word "dynamic"
                        // then add the IP address on that line to the 
                        // List<> Array...
                        if (dataArray[2].equalsIgnoreCase("dynamic")) {
                            ipList.add(dataArray[0]);
                            // For console output display only...
                            System.out.println("Device Located On IP: " + dataArray[0]);
                        }
                    }
                }
            }
            // Close the Reader
            reader.close();

            // try to connect to the device....
            // You'll need to play with this.
            try {
                for (int i = 0; i < ipList.size(); i++) {
                    ip = ipList.get(i);
                    socket.connect(new InetSocketAddress(ip, port), 1000);
                    if (socket == null) {
                        System.err.println("Could not find socket.");
                    }
                    else { 
                        System.out.println("Found socket for: " + ip); 
                    }
                    socket.close();
                }
            } catch (ConnectException | SocketTimeoutException ex) {
                System.out.println("\nSOCKET ERROR - " + ex.getMessage());
            }
        } catch (IOException | InterruptedException e) { 
            System.out.println("\nPROCESS/READER ERROR - " + e.getMessage()); 
        }
    }
}

【讨论】:

  • 每次都有socket超时异常。如果您能提供解决方案,那就太好了
  • @Aviral Ahuja,见第二个答案。我希望这可以为您解决一些问题。
【解决方案2】:

这个添加的答案是针对您关于套接字连接的第二个问题。这应该完全作为另一个主题开始,但绝不会少......

不幸的是,它不像放下一个 Socket 对象并期望它连接到您找到的设备那么简单。每个设备需要考虑几件事,例如防火墙保护、防病毒保护、设备本身的连接要求(如端口号等)。使用 80 等通用端口连接也会获得更多成功而不是像 1234 这样晦涩的东西。

在我看来,您的 Socket 连接应该更健壮一些,以便至少收到关于您的连接可能失败或成功的原因的确认。事实上(IMO),您的 Socket 连接应该完全通过不同的方法完成。

我再次为您提供另一个可运行的示例,但这次我做了一些更改并添加了更多方法。我所做的第一个更改是将 getNetworkDevices() 方法重命名为 getNetworkDeviceIPs() 并让它实际返回一个字符串 List Array检测到的设备 IP。第二个更改是我从 getNetworkDeviceIPs() 方法中删除了 Socket 连接代码,并将 Socket 连接代码放入名为 connectToDevices() 的不同方法中。

如前所述,我在如下所示的新可运行示例中添加了几个新方法。第一个方法名为 getDeviceName(),该方法从 getNetworkDeviceIPs() 方法检索的 List 数组中传递一个 IP 地址。 List 数组元素中包含的每个 IP 都通过此方法进行迭代和检查,以便在控制台中显示该设备的主机名(以及 IP 地址)。

第二个新方法(正如我们之前提到的)名为 connectToDevices(),它传递从 getNetworkDeviceIPs() 方法检索到的 List 数组。此方法将尝试打开与字符串列表 数组中包含的每个设备 IP 地址的套接字连接。此方法当前不返回任何内容(它是 void),但会在控制台窗口中显示连接结果,以了解它是否成功。您当然可以修改此方法以返回任何您喜欢的结果。

这是一个新的可运行示例,展示了上述所有项目:

package networkdevices;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;


public class NetworkDevices {
    public static int port = 80;

    public static void main(String[] args) {
        //Get devices from system ARP Table and
        // place their IP's into a List<> Array...
        List<String> ipList = getNetworkDeviceIPs(port);

        // Iterate trough the List<> Array and display
        // Device names stored within with the getDeviceName()
        // method...
        System.out.println("\nListing Device Names - Please Wait...");
        for (int i = 0; i < ipList.size(); i++) {
            System.out.println(getDeviceName(ipList.get(i)));
        }

        // Try to connect to each Device that is storred
        // within the List<> Array....
        System.out.println("\nTrying To Connect To Devices...");
        connectToDevices(ipList, port);
    }

    private static List<String> getNetworkDeviceIPs(int portNumber){
        Socket socket = new Socket();
        List<String> ipList = new ArrayList<>(); // List<> Array to hold IP Addresses

        try {
            Process process = Runtime.getRuntime().exec("arp -a"); 
            process.waitFor();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String ip = null;
            while ((ip = reader.readLine()) != null) {
                ip = ip.trim();     // Trim the data
                if (!ip.equals("")) { 
                    if (!ip.equals("")) {
                        // Remove all the unwanted spaces between data provided by 
                        // the ARP Table when it is generated.
                        while (ip.contains("  ")) { ip = ip.trim().replace("  ", " "); }
                        // Split each data line into a String Array for processing
                        String[] dataArray = ip.split(" ");
                        // For console output display only...
                        if (dataArray[0].toLowerCase().startsWith("interface:")) {
                            System.out.println("Locating Devices Connected To: " + dataArray[1]);
                        }
                        // If the data line contains the word "dynamic"
                        // then add the IP address on that line to the 
                        // List<> Array...
                        if (dataArray[2].equalsIgnoreCase("dynamic")) {
                            ipList.add(dataArray[0]);
                            // For console output display only...
                            System.out.println("Device Located On IP: " + dataArray[0]);
                        }
                    }
                }
            }
            // Close the Reader
            reader.close();
        } 
        catch (IOException | InterruptedException e) { 
            System.out.println("\nPROCESS/READER ERROR - " + e.getMessage()); 
        }
        return ipList;
    }

    private static String getDeviceName(String localIP) {
        String result = "";
        try {
            InetAddress address = InetAddress.getByName(localIP);
            if (address.isReachable(500)) {
                // Device is turned on and can be pinged!;
                result = address.toString();
            }
            else if (!address.getHostAddress().equals(address.getHostName())) {
                // Device is identified in a DNS lookup!
                result = address.toString();
            }
            else {
                // if you keep getting something like "Unknown Device!/192.168.0.5 then the host
                // address and host name are the same, meaning the host name could not be resolved.
                // This means that either your router just isn't storing the information OR those 
                // devices just choose not to submit their host name to the router, and that is why
                // you will continually get this message. Apparently, there is no way around this 
                // because those device names literally aren't stored anywhere.
                result = "Unknown Device!/" + address.toString().substring(0,address.toString().indexOf("/"));
            }
        } 
        catch (UnknownHostException ex) { System.out.println(ex.getMessage()); } 
        catch (IOException ex) { System.out.println(ex.getMessage()); }

        return result;
    }

    private static void connectToDevices(List<String> localIPAddresses, int port) {
        // try to connect to the device(s)....
        // You'll need to play with this.
        for (int i = 0; i < localIPAddresses.size(); i++) {
            if (i > 0) { System.out.println(""); }
            try {
                System.out.println("Connecting to: " + localIPAddresses.get(i) + " on port: " + 
                                   port + " - Please Wait...");
                Socket thisSystem = new Socket(localIPAddresses.get(i), port);

                System.out.println("Just connected to: " + thisSystem.getRemoteSocketAddress());
                OutputStream outToServer = thisSystem.getOutputStream();
                DataOutputStream out = new DataOutputStream(outToServer);

                out.writeUTF("Hello from: " + thisSystem.getLocalSocketAddress());
                InputStream inFromServer = thisSystem.getInputStream();
                DataInputStream in = new DataInputStream(inFromServer);

                System.out.println("Device says " + in.readUTF());
                thisSystem.close();
            }
            catch(IOException e) { System.out.println(e.getLocalizedMessage()); }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 2018-05-16
    • 1970-01-01
    • 2012-12-11
    • 1970-01-01
    相关资源
    最近更新 更多