NetworkInterface.getNetworkInterfaces()未列出所有接口

时间:2013-07-17 11:47:48

标签: java

我的机器上有三个接口(eth0,Loopback,wlan0),我想使用Java-API来获取mac地址。

  • 我使用此代码。

    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

  • 我的操作系统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&gt;&amp; 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

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

3 个答案:

答案 0 :(得分:8)

显然,我首先错了:尽管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()和JAVA API使用的ifconfig仅返回正在运行的接口。这也可以在问题的strace ifconfig ...输出中看到 - 第一个ioctl仅返回lowlan0,但不是 eth0。

然后,ifconfig从哪里获取eth0?检查ifconfig源代码(来自Debian / Ubuntu上的net-tools包),我们看到 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!!)
        ...
    }
}

答案 1 :(得分: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地址的接口就像没有它一样。您必须轮询界面或每次访问时获取它们,比如应用程序中的“网络首选项”。

答案 2 :(得分:0)

扩展@Andreas的答案,我们可以编写一个像$ifconfg | grep "Link encap" > some_file这样的小shell脚本,然后将有一个较小的(只有3行)文件来解析并选择每一行的第一个令牌。获得HWaddress的类似之处。我们将编写较小的java代码。

其他选项可能是使用Apache commons IOUtils.toString(new FileInputStream( <file_path>,US_ASCII))来读取设置。这将消除他的解决方案中重复的Java I / O代码。