Я думаю, вам нужно будет перебрать все адреса и дополнительно проверить, является ли широковещательный адрес также null
.
Учтите, что у вас также могут быть адреса, которые вы не ожидаете назначить интерфейсу. В моей системе Linux с вашим кодом первым адресом, который я вижу, является адрес IPv6 с нулевой широковещательной передачей (поскольку такой вещи, как широковещательная передача IPv6, не существует - хотя для достижения того же эффекта можно использовать многоадресную передачу).
Вам необходимо полностью удалить часть кода 1st way
. Когда вы наберете continue;
, вы перейдете к следующему интерфейсу, а не рассматриваете возможность наличия двух адресов.
Другая причина, по которой вы всегда хотите перебирать все адреса, которые могут иметь широковещательные сообщения, заключается в том, что вам нужно учитывать, что у вас могут быть адреса в двух сетях, назначенных интерфейсу. Например, у вас может быть интерфейс с назначенными 192.168.0.1/24
и 172.16.0.1/24
.
Также рассмотрите возможность использования 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;
}
}
Другая проблема, с которой вы можете столкнуться, - это попытка / отлов в основном функции whole , которая может привести к остановке этого кода, если он столкнется с чем-то неожиданным. Было бы лучше окружить возможные точки сбоя try / catch и сделать что-то вменяемое (например, пропустить интерфейс или адрес), но я не смотрел, какие методы могут генерировать исключения.
Редактировать 2 : Я неправильно прочитал ваш код; ваш итератор был в порядке. ;-) Проблема (на которую я указал ранее) заключалась в том, что ваш 1st way
закорачивает ваш 2nd way
; поскольку он попадает в оператор continue;
, если первый адрес - null
, вы даже не пытаетесь просмотреть их все.
В любом случае, запустите эти операторы println
и опубликуйте результаты, если у вас все еще есть проблемы.
Редактировать 3 : ОК, я сдаюсь. ;-) Судя по выводу, который вы разместили, похоже, что вы столкнулись с ошибкой в классе NetworkInterface
.
Я не знаю, поможет ли это отключить опцию preferIPv4Stack
, но вы должны это проверить. Я немного поискал сообщения об ошибках, описывающих это поведение, но не смог их найти.
Поскольку вы работаете в Linux, вы всегда можете прибегнуть к альтернативному подходу: выделять и вызывать что-то вроде:
/sbin/ip addr | perl -ne 'print "$1\n" if $_ =~ /inet.* brd ([0-9\.]*)/'
... который должен вернуть вам список адресов широковещания.
Редактировать 4 : Я только что заметил в JavaDoc для NetworkInterface есть вызов getSubInterfaces()
. Может быть, вам нужно позвонить, чтобы убедиться, что вы получите все адреса? (может помочь опубликовать вывод /sbin/ip addr
и /sbin/ifconfig
)
Редактировать 5 : Относительно только что добавленной награды. (Этому вопросу больше года!) Может, кто-нибудь запустит код в моем ответе выше (отредактирован, чтобы его было легко скопировать / вставить / запустить) и скажите мне, работает ли он? Если это не так, отредактируйте вопрос и запишите точные ошибки / проблемы.