用Java检测所有可用网络的广播地址
对于我的项目,我想获取所有可用广播地址的列表,以便我可以广播请求,并且位于未指定网络中其他计算机上的其他应用程序将响应并获取列表(现在使用由 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;
}
它对于常规 LAN 工作得很好,但是当涉及到 WiFi LAN 时,它只是在一步后跳过第二个 while 循环,因为 address
等于 null,即使当我使用 < code>System.out.println(interfaceItem) 只是为了查看正在通过哪些接口,它写下了无线 LAN 的名称和与该网络对应的 IP。
你能告诉我这是怎么回事吗?谢谢你!
注意:事实证明,这可能是我的笔记本的问题,而代码一般适用于其他人,我喜欢这种问题:-)对我来说似乎是一个死胡同,但无论如何还是感谢帮助:-)
仍然爱你! ;-)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您需要遍历所有地址,并另外检查广播地址是否为
null
。请考虑您可能也有不希望分配给接口的地址。在我的 Linux 系统上,使用您的代码,我看到的第一个地址是 IPv6 地址,具有空广播(因为不存在 IPv6 广播之类的东西 - 尽管您可以使用多播来达到相同的效果)。
您需要完全删除代码的
1st way
部分。当您继续;
时,您将进入下一个界面,而不是考虑有两个地址的可能性。您总是想要迭代所有可以进行广播的地址的另一个原因是您需要考虑可能在分配给一个接口的两个网络上有地址。例如,您的接口可能同时分配了
192.168.0.1/24
和172.16.0.1/24
。另外,请考虑使用
Set
来存储广播地址,以防止出现在同一子网上分配了两个地址的情况。最后,由于使用广播地址将限制您只能与在同一子网中具有 IP 地址的主机进行通信,因此您可能会错过未正确配置相同子网/网络掩码的主机。因此,您可能需要考虑为此使用多播;您可以使用 IPv4 (或 IPv6) 所有节点多播地址以到达子网上的所有主机,无论配置的地址如何。 (分别为 224.0.0.1 和 FF01::1)
编辑:
您在我将你的代码更改为这样,并且它对我有用:第二种方式
上也有一个错误,与您对迭代器的使用有关。由于每次 for 循环都会得到一个新的.iterator()
,所以幸运的是这里没有无限循环。您可能遇到的另一个问题是基本上整个函数的 try/catch,如果遇到意外的情况,这将导致此代码停止。最好用 try/catch 包围可能的故障点并做一些理智的事情(例如跳过接口或地址),但我没有查看哪些方法可以抛出异常。
编辑2:我误读了你的代码;你的迭代器很好。 ;-) 问题(我之前指出过)是你的
第一种方式
使你的第二种方式
短路;因为它命中了continue;
语句,如果第一个地址为null
,您甚至不会尝试循环遍历所有地址。无论如何,如果仍然遇到问题,请运行这些
println
语句并发布结果。编辑3:好吧,我放弃了。 ;-) 根据您发布的输出,您似乎在 NetworkInterface 类中遇到了错误。
我不知道关闭
preferIPv4Stack
选项是否有帮助,但您应该测试一下。我搜索了一些描述此行为的错误报告,但找不到任何报告。由于您使用的是 Linux,因此您始终可以采取后备方法,即调用以下内容:
... 这应该会返回一个广播地址列表。
编辑4:我刚刚在JavaDoc中注意到NetworkInterface 有一个
getSubInterfaces()
调用。也许您需要调用它以确保获得所有地址? (发布/sbin/ip addr
和/sbin/ifconfig
的输出可能会有所帮助)I think you'll need to iterate across all the addresses, and additionally check if the broadcast address is
null
as well.Consider that you might have addresses that you aren't expecting assigned to the interface as well. On my Linux system, with your code, the first address I see is an IPv6 address, with a null broadcast (since there is no such thing as an IPv6 broadcast - though you can use multicast to achieve the same effect).
You need to completely remove the
1st way
section of the code. When youcontinue;
there you'll go to the next interface instead of considering the possibility that there are two addresses.The other reason why you always want to iterate all the addresses that can have broadcasts is that you need to consider that you might have addresses on two networks assigned to an interface. For example, you might have an interface with both
192.168.0.1/24
and172.16.0.1/24
assigned.Also, consider using a
Set
to store the broadcast addresses to protect against the case where you might have two addresses on the same subnet assigned.Finally, since using broadcast addresses will restrict you to talking only to hosts that have an IP address in the same subnet, you might miss hosts that are not configured properly with the same subnet/netmask. So you might want to consider using multicast for this; you could use the IPv4 (or IPv6) all nodes multicast addresses to reach all hosts on the subnet, regardless of the configured address. (224.0.0.1 and FF01::1, respectively)
Edit:
You also have a bug on theI changed your code to this, and it works for me:2nd way
, related to your use of the iterator. Since you're getting a new.iterator()
each time around the for loop, you're lucky there isn't an infinite loop here.Another problem you may run into is the try/catch around basically the entire function, which would cause this code to stop if it hit something unexpected. It would be better to surround possible failure points with a try/catch and do something sane (like skip the interface or address), but I didn't look at which methods can throw exceptions.
Edit 2: I misread your code; your iterator was fine. ;-) The problem (which I pointed out earlier) was that your
1st way
is short-circuiting your2nd way
; since it hits thecontinue;
statement, if the first address isnull
you don't even try to loop through them all.In any case, run with those
println
statements and post the results if you're still having trouble.Edit 3: OK, I give up. ;-) Based on the output you posted, it looks like you are running into a bug in the
NetworkInterface
class.I don't know if it would help to turn off the
preferIPv4Stack
option, but you should test that. I searched around a little bit for bug reports that describe this behavior and could not find any.Since you're on Linux, you could always take the fallback approach of shelling out and calling something like:
... which should return you a list of broadcast addresses.
Edit 4: I just noticed in the JavaDoc for NetworkInterface there is a
getSubInterfaces()
call. Maybe you need to call this to make sure you get all the addresses? (it might help to post the output of/sbin/ip addr
and/sbin/ifconfig
)