获取Java中特定网络接口的名称

问题描述 投票:1回答:1

我正在使用Windows 10,我想在我的计算机上插入一个设备(该计算机创建了一个名称为“ Ethernet 12”和描述为“ foobar”的新网络接口,并能够使用以下命令设置该接口的IP地址) Java。使用此链接:Change Computer IP address using JAVA,我可以配置接口的IP地址。我遇到的问题是,在Java中,我无法检索由设备创建的接口的名称。从找到的文档中,我执行了以下操作:

    Enumeration<NetworkInterface> networkInterfaces =  NetworkInterface.getNetworkInterfaces();

    while(networkInterfaces.hasMoreElements())
    {
        NetworkInterface networkInterface = networkInterfaces.nextElement();

        if (networkInterface.isUp())
            System.out.println("Display name: " + networkInterface.getDisplayName() + "\nName: " + networkInterface.getName() + "\nAddress: " + networkInterface.getInterfaceAddresses().get(0));
    }

并获得以下结果:

    Display name: foobar
    Name: eth15
    Address 111.116.15.4

我希望该名称为“ Ethernet 12”而不是“ eth15”,这似乎没有任何意义。我在所有其他接口(wifi,以太网等)上都注意到了相同的情况。因为我需要接口的真实名称(以太网12)来使用netsh配置IP地址(而不是像“ eth15”这样的随机地址),所以我陷入了困境...

是否有我将“ eth15”作为接口名称的原因?

谢谢

java jvm network-programming network-interface
1个回答
2
投票

有没有理由将“ eth15”作为接口名称?

这需要一些挖掘。在Java世界中,NetworkInterfaces由java.net.NetworkInterface::getNetworkInterfaces()枚举,它调用native java.net.NetworkInterface::getAll()

我们可以在OpenJDK 11 getAll()中找到此注释的原始源代码:

here

因此从前,当Windows 95还是一个东西时,有人决定不读取实际的Windows接口名称,而是使用“我们自己的约定”。为什么?不知道。我希望获得一个单独的/* * Windows implementation of the java.net.NetworkInterface native methods. * This module provides the implementations of getAll, getByName, getByIndex, * and getByAddress. * * Interfaces and addresses are enumerated using the IP helper routines * GetIfTable, GetIfAddrTable resp. These routines are available on Windows * 98, NT SP+4, 2000, and XP. They are also available on Windows 95 if * IE is upgraded to 5.x. * * Windows does not have any standard for device names so we are forced * to use our own convention which is based on the normal Unix naming * convention ("lo" for the loopback, eth0, eth1, .. for ethernet devices, * tr0, tr1, .. for token ring, and so on). This convention gives us * consistency across multiple Windows editions and also consistency with * Solaris/Linux device names. Note that we always enumerate in index * order and this ensures consistent device number across invocations. */ 和一个deviceName(),但不幸的是我没有得到咨询。

基础Windows API调用ourOwnConventionWhichHasNothingToDoWithTheActualNameDeviceName()确实以GetIfTable数组的形式返回每个接口的名称:

MIB_IFROW

JVM似乎是typedef struct _MIB_IFROW { WCHAR wszName[MAX_INTERFACE_NAME_LEN]; IF_INDEX dwIndex; IFTYPE dwType; DWORD dwMtu; DWORD dwSpeed; DWORD dwPhysAddrLen; UCHAR bPhysAddr[MAXLEN_PHYSADDR]; DWORD dwAdminStatus; INTERNAL_IF_OPER_STATUS dwOperStatus; DWORD dwLastChange; DWORD dwInOctets; DWORD dwInUcastPkts; DWORD dwInNUcastPkts; DWORD dwInDiscards; DWORD dwInErrors; DWORD dwInUnknownProtos; DWORD dwOutOctets; DWORD dwOutUcastPkts; DWORD dwOutNUcastPkts; DWORD dwOutDiscards; DWORD dwOutErrors; DWORD dwOutQLen; DWORD dwDescrLen; UCHAR bDescr[MAXLEN_IFDESCR]; } MIB_IFROW, *PMIB_IFROW; ,然后是read this array,最后是generate an "appropriate" name

简而言之,实现似乎并没有改变很多年,如果不创建一个全新的API,就目前而言,不可能更改。否则,您可能会面临违反人们密码的风险。

我的看法,有两种获取实际接口名称的方法:

  1. 使用JNI自己对override the OS-provided name with the generated one进行本地调用。
  2. 执行GetIfTable并解析响应。

这两种解决方案都很难看,并且要求您确保在Windows上运行。

© www.soinside.com 2019 - 2024. All rights reserved.