用Java网络类开筛选网卡,可不是一件容易的事。如果任何条件都不加的话,使用NetworkInterface这个类,可以显示多达四十个的网络设备,直接崩溃了。可能有用的网卡就是一个或两个,这么多,是想显示自己多rich吗?
说明:以下代码中使用的Lombok插件,log是用@slf4j注解来插入的实例
如果用以往筛选正常网卡的代码大概最少也得有十行,代码如下:
try {
log.info("***************");
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
// if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) continue;
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
log.info(networkInterface.getDisplayName());
while (inetAddresses.hasMoreElements()) {
InetAddress address = inetAddresses.nextElement();
if (address instanceof Inet4Address) {
log.info("{}, {}", address.toString(), address.isSiteLocalAddress());
}
}
log.info("#################");
index++;
}
}
这些代码的核心是访问NetworkInterface中的getNetworkInterfaces中方法,把所有可用的网络设备查找出来(背后原理完全不懂,反正能用),这其中的代码(从上数第八行)的打印的log代码就可以看到每一个网络设备的提供者名字。
如果把上面代码中从上数第六行代码注释去掉,就可以筛掉几乎全部与找网卡无关的设备,但是不能筛选出虚拟机虚拟出来的网卡,但这也不是问题,知道第八行getDisplayName这个方法,就可以把VirtualBox这个提供商去掉就可以了。
第一层遍历时,还要进行第二层遍历,因为一个网卡可能有IP4与IP6两种网址,但倒数第八行的if语句把IP6的网址筛掉了。
上面代码已经可以解决问题了,但总想用Stream类来改造一下,就试用了如下的代码:
1.首先自定义一个方法:
@SneakyThrows
private static boolean isPhysicalNetCard(NetworkInterface networkInterface) {
return !networkInterface.getDisplayName().startsWith("VirtualBox") && networkInterface.isUp() &&
!networkInterface.isLoopback() && !networkInterface.isVirtual();
}
这个代码中把筛选VirtualBox的代码也写进去了
2.真正的Stream写法代码,就一行
Collections.list(NetworkInterface.getNetworkInterfaces()).stream().filter(Show::isPhysicalNetCard)
.forEach(e -> Collections.list(e.getInetAddresses()).stream()
.filter(e1 -> e1 instanceof Inet4Address).forEach(e1 -> log.info(e1.toString())));
其中的Show是整个类文件名,isPhysicalNetCard就是上面定义方法,总体写法就是依照最上面普通写法的代码用Stream来改写了一下