cn.handyplus.lib.core.NetUtil Maven / Gradle / Ivy
package cn.handyplus.lib.core;
import cn.handyplus.lib.constants.BaseConstants;
import cn.handyplus.lib.util.HandyHttpUtil;
import org.bukkit.Bukkit;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.logging.Level;
/**
* 网络相关工具
*
* @author handy
* @since 2.3.8
*/
public class NetUtil {
private NetUtil() {
}
/**
* 获得本机MAC地址
*
* @return 本机MAC地址
*/
public static String getLocalMacAddress() {
Optional macAddress = getMacAddress(getLocalhost());
return macAddress.orElseGet(HandyHttpUtil::getIp);
}
/**
* 获得指定地址信息中的MAC地址,使用分隔符“-”
*
* @param inetAddress {@link InetAddress}
* @return MAC地址,用-分隔
*/
private static Optional getMacAddress(InetAddress inetAddress) {
return getMacAddress(inetAddress, "-");
}
/**
* 获得指定地址信息中的MAC地址
*
* @param inetAddress {@link InetAddress}
* @param separator 分隔符,推荐使用“-”或者“:”
* @return MAC地址,用-分隔
*/
private static Optional getMacAddress(InetAddress inetAddress, String separator) {
if (null == inetAddress) {
return Optional.empty();
}
final byte[] mac = getHardwareAddress(inetAddress);
if (null != mac) {
final StringBuilder sb = new StringBuilder();
String s;
for (int i = 0; i < mac.length; i++) {
if (i != 0) {
sb.append(separator);
}
// 字节转换为整数
s = Integer.toHexString(mac[i] & 0xFF);
sb.append(s.length() == 1 ? 0 + s : s);
}
return Optional.of(sb.toString());
}
return Optional.empty();
}
/**
* 获得指定地址信息中的硬件地址
*
* @param inetAddress {@link InetAddress}
* @return 硬件地址
*/
private static byte[] getHardwareAddress(InetAddress inetAddress) {
if (null == inetAddress) {
return null;
}
try {
final NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inetAddress);
if (null != networkInterface) {
return networkInterface.getHardwareAddress();
}
} catch (SocketException e) {
throw new RuntimeException(e);
}
return null;
}
/**
* 获取本机网卡IP地址,规则如下:
*
*
* 1. 查找所有网卡地址,必须非回路(loopBack)地址、非局域网地址(siteLocal)、IPv4地址
* 2. 如果无满足要求的地址,调用 {@link InetAddress#getLocalHost()} 获取地址
*
*
* 此方法不会抛出异常,获取失败将返回{@code null}
*
* 见:...
*
* @return 本机网卡IP地址,获取失败返回{@code null}
*/
private static InetAddress getLocalhost() {
final LinkedHashSet localAddressList = localAddressList(address -> {
// 非 loopBack 地址,指127.*.*.*的地址
return !address.isLoopbackAddress()
&& address instanceof Inet4Address;
});
if (CollUtil.isNotEmpty(localAddressList)) {
InetAddress address2 = null;
for (InetAddress inetAddress : localAddressList) {
if (!inetAddress.isSiteLocalAddress()) {
// 非地区本地地址,指10.0.0.0 ~ 10.255.255.255、172.16.0.0 ~ 172.31.255.255、192.168.0.0 ~ 192.168.255.255
return inetAddress;
} else if (null == address2) {
address2 = inetAddress;
}
}
if (null != address2) {
return address2;
}
}
try {
return InetAddress.getLocalHost();
} catch (UnknownHostException exception) {
if (BaseConstants.DEBUG) {
Bukkit.getLogger().log(Level.SEVERE, "error:", exception);
}
}
return null;
}
/**
* 获取所有满足过滤条件的本地IP地址对象
*
* @param addressFilter 过滤器,null表示不过滤,获取所有地址
* @return 过滤后的地址对象列表
*/
private static LinkedHashSet localAddressList(Filter addressFilter) {
Enumeration networkInterfaces;
try {
networkInterfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
throw new RuntimeException(e);
}
final LinkedHashSet ipSet = new LinkedHashSet<>();
while (networkInterfaces.hasMoreElements()) {
final NetworkInterface networkInterface = networkInterfaces.nextElement();
final Enumeration inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
final InetAddress inetAddress = inetAddresses.nextElement();
if (inetAddress != null && (null == addressFilter || addressFilter.accept(inetAddress))) {
ipSet.add(inetAddress);
}
}
}
return ipSet;
}
@FunctionalInterface
private interface Filter {
/**
* 是否接受对象
*
* @param t 检查的对象
* @return 是否接受对象
*/
boolean accept(T t);
}
}