2013-07-17 13 views
15

Mam trzy interfejsy (eth0,Loopback,wlan0) na moim komputerze i chcę skorzystać z Java-API, aby uzyskać adres mac.NetworkInterface.getNetworkInterfaces() nie wymienia wszystkich interfejsów

  • Używam tego kodu.

    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())); 
    } 
    
  • Ale to kod druk wlan0,loopback, ale brakowało eth0.

  • Moje OS Ubuntu, każda pomoc.

Aktualizacja

  • O/P (strace -f java Networks 2>&1| grep ioctl) .. pusty (puste).

  • java -version

wersja java "1.7.0_21" Java (TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot (TM) 64-bitowy serwer VM (build 23.21 -B01, tryb mieszany)

  • strace 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

Czy skonfigurowano eth0? Czy pojawia się, gdy robisz "ifconfig"? –

+0

Twój kod działa dla mnie (Ubuntu 12.04 LTS) - pokazuje 'lo' i' eth0' –

+2

Jak @Erik powiedział: jaki jest wynik działania 'ifconfig'? Zarówno 'ifconfig' jak i Java API używają ostatecznie tego samego wywołania' ioctl' ('SIOCGIFCONF'), więc powinny być spójne. –

Odpowiedz

6

Oczywiście myliłem się w pierwszej kolejności: chociaż zarówno ifconfig i Java API używanego same ioctl() syscalli, zachowują się inaczej.

Przede wszystkim SIOCGIFCONF ioctl() jest udokumentowana w sposób następujący (patrz 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. 

Tak, SIOCGIFCONF ioctl() który jest wykorzystywany zarówno przez ifconfig i Java API zwraca tylko działa interfejsów. Można to również zauważyć na wyjściu z pytania strace ifconfig ... - pierwszy tylko ioctl zwraca jedynie lo i wlan0, ale nie eth0.

Następnie, gdzie ifconfig uzyskać od eth0? Sprawdzanie kodu ifconfig źródłowy (z pakietu net-tools na Debian/Ubuntu) widzimy że ifconfig nie używa wynik od ioctl() jako podstawa do wyliczenia urządzenie sieciowe, ale przede wszystkim czyta się /proc plików w celu określenia wszystkich interfejsy sieciowe. Następnie korzysta z serwerów systemowych ioctl() w celu ustalenia dalszych informacji o każdym interfejsie.

Niestety, metoda nie zwraca obiektu interfejsu sieciowego dla nieskonfigurowanego interfejsu, jeśli jawnie przekazujemy nazwę, np. eth0.

Zasadniczo, pozostają trzy różne podejścia, aby uzyskać adresy sprzętowe wszystkich urządzeń w systemie Linux:

  • połączeń ifconfig i analizowania danych wyjściowych (powinien być w ostateczności)
  • Wdrożenie bibliotekę JNI do zrób to samo, co robi ifconfig (wymaga biblioteki współdzielonej zależnej od architektury).
  • Odczytywanie danych bezpośrednio z systemów plików /proc i /sys.

Wszystkie te podejścia są zależne od systemu i nie są przenośne. Zaletą trzeciego podejścia jest to, że może on być zaimplementowany w czystej Javie. Poniżej znajduje się realizacja próbka trzecim podejściu, które sprawdziły się w moim otoczeniu:

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

Może będziesz wiedzieć, jak rozwiązać ten jeden, jak również? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-an-android-device –

0

Dzwoniąc getNetworkInterfaces Java powróci

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

Nie jesteś jedyny jeden z tym issue. Wygląda na to, że na Linuksie Java zwróci tylko interfejsy, które mają przydzielony adres IP (to jest skonfigurowane adaptery).

Jednak z punktu widzenia aplikacji (chyba, że ​​budujesz aplikację do konfiguracji sieci) posiadanie interfejsu bez adresu IP jest zupełnie niemożliwe. Będziesz musiał odpytać za interfejsy lub zdobyć je za każdym razem, gdy uzyskasz dostęp, na przykład "Preferencje sieciowe" w swojej aplikacji.

+0

Może ty Czy wiesz, jak rozwiązać ten problem? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-an-android-device –

0

Rozszerzanie @Andreas odpowiedź, moglibyśmy napisać mały skrypt jak $ifconfg | grep "Link encap" > some_file a następnie będzie mieć plik mniejszy (tylko 3 linie) przeanalizować i wybrać pierwszy token w każdym wierszu. Podobna rzecz do uzyskania HWaddress. Napiszemy mniejszy kod Java.

Inną opcją może być użycie Apache commons IOUtils.toString(new FileInputStream(<file_path>,US_ASCII)) do odczytania ustawień. To wyeliminuje powtarzalny kod I/O java w jego rozwiązaniu.

+0

Może będziesz wiedzieć, jak rozwiązać ten jeden, jak również? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-anandand-device –

Powiązane problemy