gpt4 book ai didi

java - 获取Java中特定网络接口(interface)的名称

转载 作者:行者123 更新时间:2023-11-29 04:06:02 29 4
gpt4 key购买 nike

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

    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”,这似乎没有任何意义。我注意到所有其他接口(interface)(wifi、以太网等)都一样。因为我需要我的接口(interface)(以太网 12)的真实名称来使用 netsh 配置 IP 地址(而不是像“eth15”这样的随机地址),我被卡住了......

为什么我将“eth15”作为我的界面名称?

谢谢

最佳答案

Is there a reason why I am getting "eth15" as the name of my interface ?

这需要一些挖掘。在 Java 世界中,NetworkInterfacesjava.net.NetworkInterface::getNetworkInterfaces() 枚举,它调用 native java.net。网络接口(interface)::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 数组的形式返回每个接口(interface)的名称:

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 就不可能在此时进行更改。否则,您可能会破坏他人的代码。

在我看来,有两种方法可以获取实际的接口(interface)名称:

  1. 使用 JNI 自己对 GetIfTable 进行本地调用。
  2. 执行 netsh 并解析响应。

这两种解决方案都有点丑陋,并且需要您确保在 Windows 上运行。

关于java - 获取Java中特定网络接口(interface)的名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58632235/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com