Java获取本机IP地址(屏蔽无用地址)

Java利用HostUtil工具类抓取本地IP地址(屏蔽无用地址)

一、现有的解决方法:通过黑名单屏蔽

会维护一个blackPrefixs的list类型,会屏蔽掉回环地址、ipv6以及以blackPrefixs中以"docker0", "br-", "veth"开头的地址。不是很灵活,经常会出现抓到了不以这些前缀开头的NetworkInterface,则会出现ip地址不是自己的地址的情况。

//核心逻辑
Iterator var5 = blackPrefix.iterator();

                    while(var5.hasNext()) {
                        String prefix = (String)var5.next();
                        if (networkInterface.getName().startsWith(prefix)) {
                            log.info("Network " + networkInterface.getName() + " will be ignored because it start with prefix " + prefix);
                            skip = true;
                            break;
                        }
                    }

二、通过判断是否可以连接公网

可以通过加上这样一层逻辑,在抓取到的非回环地址、非ipv6地址的基础上,进行一次socket连接。这种做法虽然可以找到能够连接外网的ipv4地址,但是比较耗费时间,另外就是客户的环境可能是与公网隔绝的环境。

try (SocketChannel socket = SocketChannel.open()) {
                    // again, use a big enough timeout
                    socket.socket().setSoTimeout(1000);

                    // bind the socket to your local interface
                    socket.bind(new InetSocketAddress(address, 8080));

                    // try to connect to *somewhere*
                    socket.connect(new InetSocketAddress("baidu.com", 80));
                } catch (IOException ex) {
                    ex.printStackTrace();
                    continue;
                }

三、给予用户一种使用方式

在console端,暴露出了business.properties配置文件,在其中定义了console.hostutil.blackPrefixs这个配置。在原来的HostUtil中的blackPrefixs利用spring的@value注解(这样还得给HostUtil类打上@Component),注入配置文件中的值,这样可以给予用户一种选择的权利,但是也不是最终的解决方案,最终的方案应该是用户无感知的那种。

private static List<String> blackPrefixs;

    @Value("${console.hostutil.blackPrefixs}")
    public void setBlackPrefixs(List<String> blackPrefixs) {
        HostUtil.blackPrefixs = blackPrefixs;
    }
## to ignore the useless network
console.hostutil.blackPrefixs="docker0", "br-", "veth", "bridge", "virbr"

附录HostUtil

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import com.google.common.collect.Lists;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class HostUtil {

    /**
     * Need ignore other useless network's ip
     */
    private static List<String> blackPrefixs;

    private static String             hostIpCache  = null;

    @Value("${console.hostutil.blackPrefixs}")
    public void setBlackPrefixs(List<String> blackPrefixs) {
        HostUtil.blackPrefixs = blackPrefixs;
    }

    public static String getHostIp() {
        if (StringUtils.isNotBlank(hostIpCache)) {
            return hostIpCache;
        } else {
            hostIpCache = getHostIpInner();
            return hostIpCache;
        }
    }

    private static String getHostIpInner() {
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            String lastMatchIP = null;
            while (interfaces.hasMoreElements()) {
                NetworkInterface networkInterface = interfaces.nextElement();
                boolean skip = false;
                for (String prefix : blackPrefixs) {
                    if (networkInterface.getName().startsWith(prefix)) {
                        log.info("Network " + networkInterface.getName() + " will be ignored because it start with prefix " + prefix);
                        skip = true;
                        break;
                    }
                }

                if (skip) {
                    continue;
                }

                Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress addr = addresses.nextElement();
                    if (addr.isLoopbackAddress()) {
                        continue;
                    }

                    lastMatchIP = addr.getHostAddress();
                    if (!lastMatchIP.contains(":")) {
                        return lastMatchIP;// return IPv4 addr
                    }
                }
            }

            if (StringUtils.isBlank(lastMatchIP)) {
                return InetAddress.getLocalHost().getHostAddress();
            } else {
                return lastMatchIP;
            }
        } catch (Exception e) {
            throw new RuntimeException("get host ip failed,msg:" + ExceptionUtils.getRootCauseMessage(e), e);
        }
    }
}
上一篇:解决springboot不能解析@ConfigurationProperties(prefix = “xxx“)


下一篇:LeetCode14.最长公共前缀