2013-07-17 6 views
15

私のマシンには3つのインターフェイス(eth0,Loopback,wlan0)があり、私はJavaアドレスを取得するためにJava-APIを使いたいと思っています。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のを逃しました。

  • 私のOS Ubuntu、あらゆるヘルプ。

更新

  • O/P(strace -f java Networks 2>&1| grep ioctl).. ブランク(空)

  • java -version

Javaのバージョン "1.7.0_21" のJava(TM)SEランタイム環境(1.7.0_21-B11を構築) は、Java HotSpot(TM)64ビットサーバーVM(23.21を構築-b01、混在モード)

  • 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

eth0は設定されていますか? 'ifconfig'を実行すると表示されますか? –

+0

あなたのコードは私のために働きます(Ubuntu 12.04 LTS) - 'lo'と' eth0'を表示します –

+2

@Erikは言った: 'ifconfig'の出力は何ですか? 'ifconfig'とJava APIの両方が最終的に同じ' 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. 

したがって、両方ifconfigおよびJava APIによって使用されるSIOCGIFCONF ioctl()のみインターフェイスを実行を返します。これはまた、質問からのstrace ifconfig ...出力で見ることができます。最初のioctllowlan0を返しますが、ではなくeth0を返します。

次に、ifconfigはどこからでもeth0を取得しますか? (Debianの/ Ubuntuでnet-toolsパッケージから)ifconfigソースコードをチェック、我々はifconfigは、ネットワークデバイスの列挙のための基礎としてioctl()からの結果を用いて が、まず全て決定する/procファイルシステムを読み出していないことを 参照しますネットワークインタフェース。次に、ioctl()のシステムコールを使用して、各インターフェイスの詳細情報を確認します。

メソッドは、eth0のように明示的に名前を渡すと、構成されていないインタフェースに対してネットワークインタフェースオブジェクト を返しません。

  • コールifconfigと出力を解析するためにJNIライブラリを実装
  • (最後の手段でなければなりません):基本的に

    、Linux上ですべてデバイスのハードウェアアドレスを取得するための3つの異なるアプローチが残っていますifconfigと同じ操作を行う(アーキテクチャに依存する共有ライブラリが必要)

  • /proc/sysファイルシステムから直接データを読み込みます。

これらのアプローチはすべてシステムに依存し、移植性がありません。 3番目のアプローチの利点は、純粋な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.

あなただけではありませんが返されます1つは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 I/Oコードが排除されます。

+0

この問題を解決する方法もわかりますか? https://stackoverflow.com/questions/45607188/not-receiving-all-network-interfaces-of-an-android-device –

関連する問題