【问题标题】:Java - find host by MAC addressJava - 通过 MAC 地址查找主机
【发布时间】:2011-11-26 09:24:25
【问题描述】:

我有一个 Java/Android 应用程序,它需要向本地网络上的服务器发送一些数据。问题是服务器的IP地址是动态的,所以找到它的唯一方法是通过它的MAC地址查找。 这在Java中可能吗?你还能看到其他选项吗?

【问题讨论】:

  • 我怀疑 MAC 地址查找是否可行,但您不能通过主机名连接吗?因此,您将连接到www.google.com,而不是74.125.237.116

标签: java android network-programming


【解决方案1】:

通过 MAC 地址查找主机只能在您的本地网络中使用。 Mac 地址是 IP 地址下的一层。不存在基于 Mac 地址到其他网络的路由。

广播/组播

如果您正在寻找仅适用于本地网络的解决方案,那么您可以选择监听并发送到广播或多播。如果您将数据包发送到广播地址,则本地网络中的每个主机都会收到此数据包,并且可以回答是否是您正在寻找的服务器。多播在概念上的不同之处在于,只有想要接收寻址到特定多播地址的数据包的主机才能接收此数据包。如果您使用多播,您需要为您的应用程序选择一个地址,每个客户端都将数据包发送到该地址,每个要找到的服务器都侦听该地址。甚至存在一些网络(例如一些大学网络),其中多播数据包被路由到一组有限的其他本地网络。

DNS 或其他静态服务器

您可以使用具有静态 IP 地址的第二台服务器来查找您的动态服务器。您的动态服务器会在其更改时告诉您的静态服务器他的 IP 地址。您的客户端会向静态服务器询问动态服务器的地址。这种模式适用于整个互联网,无论您的动态服务器和客户端在哪里。

此静态服务器可能是您的 DNS 服务器或某些 dyndns 提供商的 dns 服务器。但这不仅限于 DNS。 DNS 旨在找出如何访问服务/服务器,但这可以通过任何协议完成。例如,如果您更喜欢 web 服务,这可以通过您开发的一些 http/web 应用程序来完成。

【讨论】:

    【解决方案2】:

    只是一点警告:此代码未经测试,

    尝试挖掘 arp 缓存,如下所示:

    public static String getIpFromArpCache(String macaddr) {
        if (ip == null)
            return null;
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("/proc/net/arp"));
            String line;
            while ((line = br.readLine()) != null) {
                String[] splitted = line.split(" +");
                if (splitted != null && splitted.length >= 4 && macaddr.equals(splitted[3])) {
                    // Basic sanity check
                    String ip = splitted[0];
                    if (validateIp(ip)) {
                        return ip;
                    } else {
                        return null;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    
    private static final String PATTERN = 
        "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
    
    public static boolean validateIp(final String ip){          
    
          Pattern pattern = Pattern.compile(PATTERN);
          Matcher matcher = pattern.matcher(ip);
          return matcher.matches();             
    }
    

    来自here的修改例程

    【讨论】:

    • 这并不意味着 MAC 会在本地缓存中。因此,在某些情况下它可能有效,但也可能无效。
    • 我知道,你是对的,他可能必须在这样做之前进行多播。我会在周末之后测试它并更新答案。
    【解决方案3】:

    这在 Java 中可行吗?

    不是在纯 Java 中。

    没有直接将 MAC 地址映射到 IP 地址的服务。主机操作系统的网络堆栈使用 ARP 协议和(在 Linux/UNIX 上)ARP daemon 将 IP 地址映射到 MAC 地址。 AFAIK,无法使用 Java 的 ARP 协议。

    (在 Linux 上)您能做的最好的事情就是将“arpd -l”作为外部命令运行。这将以您的 Java 应用程序可以读取和解析的定义明确的格式转储守护程序的 ARP 映射。如果您的服务器在本地网络上处于活动状态,则其 MAC 地址将与相应的 IP 地址一起出现。但如果它不在本地网络上,那么它的 ARP 广播将不会到达您的机器,因此守护程序的表中不会有条目。


    最好为您的服务器分配一个静态 IP 地址……和一个 DNS 地址。另一种可能性是让服务器使用Dynamic DNS 服务注册自己。

    【讨论】:

    • 你可以通过广播,查询 MAC NetworkInterface.getHardwareAddress() 并检查它是否符合条件,即服务器必须合作。如果安卓设备真的可以广播,那就另当别论了。
    • @bestsss - 这可能行不通。在常规 ARP 中,您广播 IP 地址并取回 MAC 地址。除非服务器实现反向 ARP - tools.ietf.org/html/rfc2390 - 您不能请求 IP 地址作为 MAC 地址。
    • 我的意思是包含 MAC 作为有效负载的常规广播,如果它已在该 MAC 上启动(因此是合作的),服务器应回复广播。只是发现。第二,虽然也可以采用残酷的方法,只需发送到网络中的所有 IP,如端口扫描器。
    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 2016-07-08
    • 2013-02-21
    相关资源
    最近更新 更多