Java查找默认网关的网络接口

Java查找默认网关的网络接口,java,routing,network-programming,Java,Routing,Network Programming,在Java中,我想找到与默认网关使用的接口对应的Java.net.NetworkInterface。接口的名称等都是事先不知道的 换句话说,如果下面是我的路由表,我希望接口与“bond0”对应: 在谷歌搜索之后,我仍然没有找到任何答案 编辑: java运行时必须“知道”如何获取这些信息(不是说它是公开的)。当使用join(InetAddress grpAddr)调用(未指定接口)将java.net.MulticastSocket加入到多播组时,明显的行为似乎是在“默认”接口上加入(如上定义)。即

在Java中,我想找到与默认网关使用的接口对应的Java.net.NetworkInterface。接口的名称等都是事先不知道的

换句话说,如果下面是我的路由表,我希望接口与“bond0”对应:

在谷歌搜索之后,我仍然没有找到任何答案

编辑:
java运行时必须“知道”如何获取这些信息(不是说它是公开的)。当使用join(InetAddress grpAddr)调用(未指定接口)将java.net.MulticastSocket加入到多播组时,明显的行为似乎是在“默认”接口上加入(如上定义)。即使默认intf不是路由表中列出的第一个接口,这也可以工作。但是,加入mcast组的基础POSIX调用需要以下信息!:

struct ip_mreqn group;
group.imr_multiaddr = ...
group.imr_address = **address of the interface!**
setsockopty(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group));

要点:通过提供一种加入不需要intf的多播组的方法,java平台隐式地必须知道如何在每个平台上确定适当的intf。

据我所知,这是没有好办法的,因为这样的低级细节对于Java来说很难以跨平台的方式实现。java.net.NetworkInterface可能会有所帮助,但如果可用的方法不够,您可能不得不求助于更丑陋的方法

这是将永远在指定平台上运行的东西,还是需要更具可移植性?在最坏的情况下,您可以尝试执行系统命令并解析输出,但这不是非常可移植或稳定的

一些相关主题:

我的方式是:

try(DatagramSocket s=new DatagramSocket())
{
    s.connect(InetAddress.getByAddress(new byte[]{1,1,1,1}), 0);
    return NetworkInterface.getByInetAddress(s.getLocalAddress()).getHardwareAddress();
}

由于使用了数据报(UDP),它没有连接到任何地方,因此端口号可能毫无意义,远程地址(
1.1.1.1
)不需要访问,只需要路由即可。

好的,我明白你的意思。然而,看起来那个电话仍然需要一个地址,是吗?NetworkInterface可以获得接口(及其地址),稍微聪明一点就可以决定谁拥有给定的地址。我认为您的问题更复杂,因为您首先查找较低级别的路由信息,然后向后查找与(默认)路由关联的接口。它需要多播地址(即224.xxx-239.xxx中的特殊地址),而不是接口的地址。论点中没有提供此类信息。因此,“join”调用必须解决的问题是相同的。它神奇地选择了具有默认路由(明显行为)的路由。类似地,我想知道哪个接口有默认路由。我想,如果真的没有使用def路由查找intf的公开方法,我只是有点沮丧,因为以平台索引方式确定intf的问题似乎在幕后解决了。当然,要明确的是,我还没有“证明”join总是选择正确的intf(但根据经验,它总是有效的!)。所以我只能假设,在幕后,它知道…明白。因此,如果它真的在幕后找到了答案,您可能会做一件丑陋的事情,使用
java.net.MulticastSocket
加入默认接口,然后使用
MulticastSocket.getNetworkInterface
getInterface
找出它选择了哪一个。然后离开小组。这不是很安全,因为您无缘无故地打开了多播套接字,所以这当然不是一个理想的解决方案。根据我的经验,这在windows和ipv6中不起作用。getLocalAddress返回一个伪造的v4地址,尽管在Windows10和Hyper-V上为我绑定了一个v6 socketWorks,并启用了Microsoft android emulator、docker和OpenVPN。请注意,如果该地址不可路由(例如,因为没有默认路由,或者您位于仅IPv6的网络上),则,然后
NetworkInterface.getByInetAddress()
将返回
null
。这是一种检测网络配置是否有效的好方法。
try(DatagramSocket s=new DatagramSocket())
{
    s.connect(InetAddress.getByAddress(new byte[]{1,1,1,1}), 0);
    return NetworkInterface.getByInetAddress(s.getLocalAddress()).getHardwareAddress();
}