我将“eth15”作为我的接口名称有什么原因吗?
这需要一些挖掘。在 Java 世界中,NetworkInterfaces 由 java.net.NetworkInterface::getNetworkInterfaces() 枚举,它调用 native 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,现在可能无法改变。否则你可能会破坏别人的密码。
在我看来,有两种方法可以获取实际的接口名称:
- 使用 JNI 自己对
GetIfTable 进行本机调用。
- 执行
netsh 并解析响应。
这两种解决方案都有点难看,并且要求您确保在 Windows 上运行。