当前位置: 首页 > 面试题库 >

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

陶高扬
2023-03-14
问题内容

(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).. blank(empty)

  • java -version

Java版本“ 1.7.0_21” Java™SE运行时环境(内部版本1.7.0_21-b11)JavaHotSpot(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)

问题答案:

显然,我一开始就错了:即使两者ifconfig和Java API都使用相同的ioctl()syscall,它们的行为也有所不同。

首先,SIOCGIFCONF ioctl()文档记录如下(请参阅http://linux.die.net/man/7/netdevice):

**SIOCGIFCONF**
    返回接口(传输层)地址的列表。
    ...
    内核使用所有当前的L3接口填充ifreqs **正在运行的** 
    地址。

因此,SIOCGIFCONF ioctl()两者ifconfig和JAVA API 都使用的,仅返回 正在运行的 接口。strace ifconfig ...在问题的输出中也可以看到这一点-第一个ioctl仅返回loand wlan0而不 返回eth0。

那么,从哪儿ifconfig得到的eth0呢?检查ifconfig代码(来自net-toolsDebian /
Ubuntu上的软件包),我们发现它ifconfig没有使用s的结果ioctl()作为网络设备枚举的基础,而是首先读取/proc文件系统以确定所有网络接口。然后,它使用ioctl()syscall来确定有关每个接口的更多信息。

不幸的是,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!!)
        ...
    }
}


 类似资料:
  • 问题内容: 为什么我们不能在MySQL中使用*关键字进行连接? 要么 还有其他方法可以访问列中的值而无需显式使用列名吗? 问题答案: 要连接表中的所有列,不能使用关键字,但是需要显式列出所有列: 或者您可能想使用它将跳过空值的方法: 如果您不想手动指定所有列名,则可以使用动态查询。该查询将返回表的所有列名称: 并使用GROUP_CONCAT,您可以获得所有列名称的列表: 用逗号分隔的格式引用: 因

  • List< TableInfo > findAllTables() 功能 列出该开发者帐号下的所有表的信息 方法参数 void 方法返回值 tableInfos : List< TableInfo > 返回表信息的列表,每个TableInfo对象代表一张表的信息 TableInfo 1.name, 表名 2.spec, 表结构和元数据,包括表的实体组键、主键、属性、二级索引、空间大小配额和读写配额

  • 问题内容: 我有一个MySQL表,该表的字段以格式存储所有成员的生日(注意:它具有“年份”部分) 我试图找到正确的SQL来: 列出未来14天内的所有生日 和另一个查询到: 列出过去14天内的所有生日 通过以下方式直接比较当前日期: 由于当前年份和DOB年份不同,因此不会获取任何内容。 但是,将DOB转换为“今年”根本不起作用,因为今天可能是1月1日,而候选人的DOB可能是12月31日(反之亦然)

  • 我使用YouTube数据API从一个频道获取视频信息。API响应不包括上传到相应频道的所有视频。 这是频道(现在有6个视频):https://www.youtube.com/channel/UCdSjDEx46aNP0oKPN_J6hOA/videos 视频列表(现在):https://i.ibb.co/K91bJxS/image.png 这是我的API调用:https://www.googlea

  • 本节,我们要添加倒数第二个用户控制器动作,index。index 动作不是显示某一个用户,而是显示所有用户。在这个过程中,我们要学习如何在数据库中生成示例用户数据,以及如何分页显示用户列表,让首页显示任意数量的用户。用户列表、分页链接和“Users”(所有用户)导航链接的构思图如图 9.8 所示。[6]9.4 节会添加管理功能,用来删除用户。 图 9.8:用户列表页面的构思图 9.3.1 用户列表

  • 问题内容: 有没有一种方法可以获取实例中所有数据库中所有存储过程中引用的所有列和表?输出应为: 问题答案: 这将得到您想要的列表,但是,如果您在动态SQL中嵌入了此类列引用(并且可能找不到依赖于延迟名称解析的引用),则将无济于事。SQL Server不会解析存储过程的文本以提供DMV输出。 现在尝试使用子句来处理在同一服务器上具有不同归类的数据库的情况。 如果您的数据库处于80兼容模式,那么该语法