我正在使用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”作为接口名称的原因?
谢谢
答案 0 :(得分:3)
我为什么要使用“ eth15”作为接口名称?
这需要一些挖掘。在Java世界中,java.net.NetworkInterface::getNetworkInterfaces()
枚举了NetworkInterfaces,它称为本地 java.net.NetworkInterface::getAll()
。
我们可以在OpenJDK 11 here中找到getAll()
的本地源代码,在其中找到以下注释:
/*
* 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.
*/
因此,曾几何时,当Windows 95还是一个东西时,有人决定不读取实际的Windows接口名称,而是使用“我们自己的约定”。为什么?不知道。我本来希望分别得到一个deviceName()
和一个ourOwnConventionWhichHasNothingToDoWithTheActualNameDeviceName()
,但不幸的是没有得到我的咨询。
基础Windows API调用GetIfTable确实以MIB_IFROW数组的形式返回每个接口的名称:
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;
JVM似乎先read this array,然后generate an "appropriate" name,最后是override the OS-provided name with the generated one。
简而言之,实现似乎并没有改变很多年,并且如果不创建一个全新的API,现在就不可能更改。否则,您有可能会违反人们的密码。
我认为,有两种获取实际接口名称的方法:
GetIfTable
进行本地调用。netsh
并解析响应。这两种解决方案都很难看,要求您确保在Windows上运行。