2013-07-17 3 views
15

У меня есть три интерфейса (eth0,Loopback,wlan0) на моей машине, и я хочу использовать Java-API для получения адреса mac.NetworkInterface.getNetworkInterfaces() не перечисляет все интерфейсы

  • Я использую этот код.

    Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); 
        for (NetworkInterface netint : Collections.list(nets)) 
         displayInterfaceInformation(netint); 
    } 
    
    static void displayInterfaceInformation(NetworkInterface netint) 
        throws SocketException 
    { 
        System.out.println("Display name: " 
         + netint.getDisplayName()); 
        System.out.println("Hardware address: " 
         + Arrays.toString(netint.getHardwareAddress())); 
    } 
    
  • Но что код печати wlan0,loopback, но пропустил eth0.

  • My OS Ubuntu, любая помощь.

Update

  • о/р (strace -f java Networks 2>&1| grep ioctl) .. пустой (пустой).

  • java -version

ява версия "1.7.0_21" Java (TM) SE Runtime Environment (сборка 1.7.0_21-b11) Java HotSpot (TM) 64-разрядного сервера VM (сборка 23.21 -b01, смешанный режим)

  • Трассирование Ifconfig 2> & 1 | Grep IOCTL

ioctl(4, SIOCGIFCONF, {80, {{"lo", {AF_INET, inet_addr("127.0.0.1")}}, {"wlan0", {AF_INET, inet_addr("192.168.1.101")}}}}) = 0 
ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_MULTICAST}) = 0 
ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=-----------------}) = 0 
ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0 
ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0 
ioctl(5, SIOCGIFMAP, {ifr_name="eth0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 
ioctl(5, SIOCGIFMAP, {ifr_name="eth0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 
ioctl(5, SIOCGIFTXQLEN, {ifr_name="eth0", ifr_qlen=1000}) = 0 
ioctl(4, SIOCGIFADDR, {ifr_name="eth0", ???}) = -1 EADDRNOTAVAIL (Cannot assign requested address) 
ioctl(5, SIOCGIFFLAGS, {ifr_name="lo", ifr_flags=IFF_UP|IFF_LOOPBACK|IFF_RUNNING}) = 0 
ioctl(5, SIOCGIFHWADDR, {ifr_name="lo", ifr_hwaddr=00:00:00:00:00:00}) = 0 
ioctl(5, SIOCGIFMETRIC, {ifr_name="lo", ifr_metric=0}) = 0 
ioctl(5, SIOCGIFMTU, {ifr_name="lo", ifr_mtu=16436}) = 0 
ioctl(5, SIOCGIFMAP, {ifr_name="lo", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 
ioctl(5, SIOCGIFMAP, {ifr_name="lo", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 
ioctl(5, SIOCGIFTXQLEN, {ifr_name="lo", ifr_qlen=0}) = 0 
ioctl(4, SIOCGIFADDR, {ifr_name="lo", ifr_addr={AF_INET, inet_addr("127.0.0.1")}}) = 0 
ioctl(4, SIOCGIFDSTADDR, {ifr_name="lo", ifr_dstaddr={AF_INET, inet_addr("127.0.0.1")}}) = 0 
ioctl(4, SIOCGIFBRDADDR, {ifr_name="lo", ifr_broadaddr={AF_INET, inet_addr("0.0.0.0")}}) = 0 
ioctl(4, SIOCGIFNETMASK, {ifr_name="lo", ifr_netmask={AF_INET, inet_addr("255.0.0.0")}}) = 0 
ioctl(5, SIOCGIFFLAGS, {ifr_name="wlan0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0 
ioctl(5, SIOCGIFHWADDR, {ifr_name="wlan0", ifr_hwaddr=---------------}) = 0 
ioctl(5, SIOCGIFMETRIC, {ifr_name="wlan0", ifr_metric=0}) = 0 
ioctl(5, SIOCGIFMTU, {ifr_name="wlan0", ifr_mtu=1500}) = 0 
ioctl(5, SIOCGIFMAP, {ifr_name="wlan0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 
ioctl(5, SIOCGIFMAP, {ifr_name="wlan0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 
ioctl(5, SIOCGIFTXQLEN, {ifr_name="wlan0", ifr_qlen=1000}) = 0 
ioctl(4, SIOCGIFADDR, {ifr_name="wlan0", ifr_addr={AF_INET, inet_addr("192.168.1.101")}}) = 0 
ioctl(4, SIOCGIFDSTADDR, {ifr_name="wlan0", ifr_dstaddr={AF_INET, inet_addr("192.168.1.101")}}) = 0 
ioctl(4, SIOCGIFBRDADDR, {ifr_name="wlan0", ifr_broadaddr={AF_INET, inet_addr("192.168.1.255")}}) = 0 
ioctl(4, SIOCGIFNETMASK, {ifr_name="wlan0", ifr_netmask={AF_INET, inet_addr("255.255.255.0")}}) = 0 

Ifconfig

$ ifconfig 
eth0  Link encap:Ethernet HWaddr ------------- 
      UP BROADCAST MULTICAST MTU:1500 Metric:1 
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:1000 
      RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) 

lo  Link encap:Local Loopback 
      inet addr:127.0.0.1 Mask:255.0.0.0 
      inet6 addr: ::1/128 Scope:Host 
      UP LOOPBACK RUNNING MTU:16436 Metric:1 
      RX packets:1695 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:1695 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:0 
      RX bytes:129949 (129.9 KB) TX bytes:129949 (129.9 KB) 

wlan0  Link encap:Ethernet HWaddr ------------------- 
      inet addr:192.168.1.101 Bcast:192.168.1.255 Mask:255.255.255.0 
      inet6 addr: fe80::-------------- Scope:Link 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 
      RX packets:8396 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:5524 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:1000 
      RX bytes:3959941 (3.9 MB) TX bytes:1513934 (1.5 MB) 
+8

Установлен ли eth0? Он появляется, когда вы делаете 'ifconfig'? –

+0

Ваш код работает для меня (Ubuntu 12.04 LTS) - он показывает 'lo' и' eth0' –

+2

Как сказал @Erik: что такое вывод 'ifconfig'? И 'ifconfig', и API Java в конечном итоге используют один и тот же вызов' ioctl' ('SIOCGIFCONF'), поэтому они должны быть согласованы –

ответ

6

Очевидно, я был не прав, в первую очередь: несмотря на то, как ifconfig и Java API, который используется тех же ioctl() системных вызовов, они ведут себя по-разному.

Прежде всего, SIOCGIFCONF ioctl() документирован следующим образом (см http://linux.die.net/man/7/netdevice):

 
SIOCGIFCONF 
    Return a list of interface (transport layer) addresses. 
    ... 
    The kernel fills the ifreqs with all current L3 interface 
    addresses that are running. 

Итак, SIOCGIFCONF ioctl(), который используется как ifconfig и JAVA API возвращает только работает интерфейсы. Это также можно увидеть на выходе strace ifconfig ... - вопрос о самом первом ioctl возвращает lo и wlan0, но не eth0.

Затем, где ifconfig получить eth0 от всего? Проверка ifconfig исходный код (из net-tools пакета на Debian/Ubuntu), мы видим , что ifconfig не использует результат от ioctl() в качестве основы для подсчета сетевого устройства, , но в первую очередь считывает /proc файловой системы, чтобы определить, все сетевых интерфейсов. Затем для определения дополнительной информации о каждом интерфейсе используются системные вызовы ioctl().

К сожалению, метод java.net.NetworkInterface.getByName() даже не возвращает объект сетевого интерфейса для неконфигурированного интерфейса, если мы явно передаем имя, например eth0.

По существу, остаются три различных подхода, чтобы получить аппаратные адреса всех устройств на Linux:

  • Вызов ifconfig и разобрать вывод (должен быть последним средством)
  • Реализация библиотеки JNI для делают то же самое, что и ifconfig (требуется общая библиотека, зависящая от архитектуры)
  • Прочитайте данные непосредственно с /proc и /sys файловых систем.

Все эти подходы зависят от системы и не переносятся. Преимущество третьего подхода состоит в том, что он может быть реализован в чистой Java. Ниже приводится пример реализации третьего подхода, который хорошо работает в моей среде:

static void printHardwareAddresses() throws SocketException { 
    if (System.getProperty("os.name").equals("Linux")) { 

     // Read all available device names 
     List<String> devices = new ArrayList<>(); 
     Pattern pattern = Pattern.compile("^ *(.*):"); 
     try (FileReader reader = new FileReader("/proc/net/dev")) { 
      BufferedReader in = new BufferedReader(reader); 
      String line = null; 
      while((line = in.readLine()) != null) { 
       Matcher m = pattern.matcher(line); 
       if (m.find()) { 
        devices.add(m.group(1)); 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     // read the hardware address for each device 
     for (String device : devices) { 
      try (FileReader reader = new FileReader("/sys/class/net/" + device + "/address")) { 
       BufferedReader in = new BufferedReader(reader); 
       String addr = in.readLine(); 

       System.out.println(String.format("%5s: %s", device, addr)); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

    } else { 
     // use standard API for Windows & Others (need to test on each platform, though!!) 
     ... 
    } 
} 
+0

Возможно, вы узнаете, как решить эту проблему? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-an-android-device –

0

При вызове getNetworkInterfaces Java вернет

all the interfaces on this machine. Returns null if no network interfaces could be found on this machine.

Вы не только один с этим issue. По-видимому, на linux Java вернет только интерфейсы, которые имеют выделенный IP-адрес (т. Е. Настроенные адаптеры).

Но с вашей точки зрения приложения (если вы не создаете приложение сетевой конфигурации), имеющего интерфейс без IP-адреса, похоже на отсутствие его. Вам придется либо опросить интерфейсы, либо получить их каждый раз, когда вы получаете доступ, скажем, «Настройки сети» в своем приложении.

+0

Возможно, вы Я знаю, как решить эту проблему? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-an-android-device –

0

Расширение @Andreas ответ, мы могли бы написать небольшой скрипт, как $ifconfg | grep "Link encap" > some_file и затем будет иметь меньший размер файла (только 3 строки) для анализа и выбора первого токена в каждой строке. Подобная вещь для получения HWaddress. Мы напишем меньший код Java.

Другим вариантом может быть использование общих ресурсов Apache IOUtils.toString(new FileInputStream(<file_path>,US_ASCII)) для ознакомления с настройками. Это позволит устранить повторяющийся код ввода/вывода Java в его решении.

+0

Возможно, вы узнаете, как решить эту проблему? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-an-android-device –

Смежные вопросы