For my project I wanted to get a list of all available broadcast addresses so I could broadcast a request and my other application located on other computer in the unspecified network would respond and to get the list I (now using little modified version with contribution of Mike) came up with this:
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;
}
It works quite well for reqular LAN however when it comes to the WiFi LAN it just skips the second while loop after one step because of having address
equals null even though when I used System.out.println(interfaceItem)
just to view what interfaces are being gone through it wrote wireless LAN's name and my IP corresponding to the network.
EDIT 1: This is the output where 172.16.1.104 is my IP in the wireless network. The problem appears ONLY on my notebook with Wifi. The output is from my notebook where I mostly use wireless and sometimes I use UTP to connect with my friend. There is also one network interface of VirtualBox on my notebook.
Could you tell me what's wrong with it? Thank you!
Note: So it turns out that this might be problem for my notebook in particular and the code works for everybody else in general, I love this kind of problem :-) Seems like a dead end to me but thank for help anyway :-)
Still love you! ;-)
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 code. When you continue;
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 because 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
and 172.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 the I 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.
$ 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;
}
}
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 your 2nd way
; since it hits the continue;
statement, if the first address is null
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:
/sbin/ip addr | perl -ne 'print "$1\n" if $_ =~ /inet.* brd ([0-9\.]*)/'
... 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 in order to make sure you get all the addresses? (it might help to post the output of /sbin/ip addr
and /sbin/ifconfig
)
Edit 5: Regarding the just-added bounty. (This question is over a year old!) Could someone please run the code in my answer above (edited to make it easy to copy/paste/run) and tell me if it works? If it doesn't, please edit the question and note the exact errors/problems.