用Java检测所有可用网络的广播地址

Mar*_*tin 15 java networking broadcast

对于我的项目,我希望获得所有可用广播地址的列表,以便我可以广播请求,而位于未指定网络中的其他计算机上的其他应用程序将响应并获取列表I(现在使用很少的修改版本和Mike的贡献想出了这个:


private ArrayList<InetAddress> getBroadcastAddresses() {
        ArrayList<InetAddress> listOfBroadcasts = new ArrayList();
        Enumeration list;
        try {
            list = NetworkInterface.getNetworkInterfaces();

            while(list.hasMoreElements()) {
                NetworkInterface iface = (NetworkInterface) list.nextElement();

                if(iface == null) continue;

                if(!iface.isLoopback() && iface.isUp()) {
                    System.out.println("Found non-loopback, up interface:" + iface);

                    Iterator it = iface.getInterfaceAddresses().iterator();
                    while (it.hasNext()) {
                        InterfaceAddress address = (InterfaceAddress) it.next();

                        System.out.println("Found address: " + address);

                        if(address == null) continue;
                        InetAddress broadcast = address.getBroadcast();
                        if(broadcast != null) listOfBroadcasts.add(broadcast);
                    }
                }
            }
        } catch (SocketException ex) {
            return new ArrayList<InetAddress>();
        }

        return site;
}

它适用于reqular局域网但是当涉及到WiFi LAN时它只是在一步之后跳过第二个while循环因为address等于null,即使我System.out.println(interfaceItem)只是用来查看正在通过它的接口写了无线LAN的名字和我的IP对应网络.

编辑1: 是172.16.1.104是无线网络中的IP的输出.问题只出现在我的Wifi笔记本上.输出来自我的笔记本,我主要使用无线,有时我使用UTP连接我的朋友.我的笔记本上还有一个VirtualBox的网络接口.

你能告诉我它有什么问题吗?谢谢!

注意:事实证明这对我的笔记本来说可能是个问题而且代码适用于其他所有人一般,我喜欢这样的问题:-)对我来说似乎是一个死胡同但是无论如何感谢帮助:-)

还爱你!;-)

mpo*_*llo 5

我认为你需要遍历所有地址,并另外检查广播地址是否null也是如此.

请考虑您可能具有您不希望分配给接口的地址.在我的Linux系统上,使用您的代码,我看到的第一个地址是IPv6地址,具有空广播(因为没有IPv6广播这样的东西 - 尽管您可以使用多播来实现相同的效果).

您需要完全删除1st way代码部分.当你continue;在那里时,你将转到下一个界面,而不是考虑有两个地址的可能性.

您总是希望迭代可以拥有广播的所有地址的另一个原因是您需要考虑在分配给接口的两个网络上可能有地址.例如,您可能具有两者的接口192.168.0.1/24并已172.16.0.1/24分配.

此外,请考虑使用a Set来存储广播地址,以防止在指定的同一子网上有两个地址的情况.

最后,由于使用广播地址会限制您只与同一子网中具有IP地址的主机通信,因此您可能会错过未使用相同子网/网络掩码正确配置的主机.所以你可能想考虑为此使用多播; 您可以使用IPv4(或IPv6)所有节点多播地址来访问子网上的所有主机,无论配置的地址如何.(分别为224.0.0.1和FF01 :: 1)

编辑:您还有一个2nd way与使用迭代器相关的错误.因为你.iterator()每次都在for循环中获得一个新的东西,你很幸运,这里没有无限循环.我将您的代码更改为此,它适用于我:

$ cat Broadcasts.java 
import java.net.*;
import java.util.*;

public class Broadcasts
{
    public static void main(String[] args)
    {
        HashSet<InetAddress> listOfBroadcasts = new HashSet<InetAddress>();
        Enumeration list;
        try {
            list = NetworkInterface.getNetworkInterfaces();

            while(list.hasMoreElements()) {
                NetworkInterface iface = (NetworkInterface) list.nextElement();

                if(iface == null) continue;

                if(!iface.isLoopback() && iface.isUp()) {
                    //System.out.println("Found non-loopback, up interface:" + iface);

                    Iterator it = iface.getInterfaceAddresses().iterator();
                    while (it.hasNext()) {
                        InterfaceAddress address = (InterfaceAddress) it.next();
                        //System.out.println("Found address: " + address);
                        if(address == null) continue;
                        InetAddress broadcast = address.getBroadcast();
                        if(broadcast != null) 
                        {
                            System.out.println("Found broadcast: " + broadcast);
                            listOfBroadcasts.add(broadcast);
                        }
                    }
                }
            }
        } catch (SocketException ex) {
            System.err.println("Error while getting network interfaces");
            ex.printStackTrace();
        }

        // return listOfBroadcasts;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能遇到的另一个问题是try/catch基本上是整个函数,这会导致此代码在遇到意外情况时停止.最好用try/catch包围可能的失败点并做一些理智的事情(比如跳过接口或地址),但我没看看哪些方法可以抛出异常.

编辑2:我误读了你的代码; 你的迭代器很好.;-)问题(我之前指出)是你1st way的短路2nd way; 因为它击中了continue;声明,如果第一个地址是null你甚至没有尝试循环它们全部.

在任何情况下,println如果您仍然遇到问题,请运行这些语句并发布结果.

编辑3:好的,我放弃了.;-)根据您发布的输出,看起来您遇到了NetworkInterface类中的错误.

我不知道是否有助于关闭该preferIPv4Stack选项,但你应该测试一下.我搜索了一下描述这种行为并且找不到的bug报告.

既然你在Linux上,你总是可以采用后备方法来解决并调用类似于:

/sbin/ip addr | perl -ne 'print "$1\n" if $_  =~ /inet.* brd ([0-9\.]*)/'
Run Code Online (Sandbox Code Playgroud)

...应该返回一个广播地址列表.

编辑4:我刚刚在JavaDoc for NetworkInterface中注意到有一个getSubInterfaces()调用.也许您需要调用它以确保获得所有地址?(它可能会帮助到后期的输出/sbin/ip addr/sbin/ifconfig)

编辑5:关于刚加入的赏金.(这个问题已经超过一年了!)有人可以在上面的答案中运行代码(编辑以便于复制/粘贴/运行)并告诉我它是否有效?如果没有,请编辑问题并记下确切的错误/问题.