Java獲取本機IP

服務(wù)器或PC一般都擁有多個網(wǎng)卡,每個網(wǎng)卡擁有一個IP地址,但并不是所有的IP地址能被外部或局域網(wǎng)訪問,比如說虛擬機網(wǎng)卡地址等等。也就是說InetAddress.getLocalHost().getHostAddress()的IP不一定是正確的IP。本文介紹兩種方式,可以在絕對部分場景下獲取到想要的IP地址。

通過過濾獲取IP地址

過濾回環(huán)網(wǎng)卡、點對點網(wǎng)卡、非活動網(wǎng)卡、虛擬網(wǎng)卡并要求網(wǎng)卡名字是eth或ens開頭;再過濾回環(huán)地址,并要求是內(nèi)網(wǎng)地址(非外網(wǎng))

public static List<Inet4Address> getLocalIp4AddressFromNetworkInterface() throws SocketException {
    List<Inet4Address> addresses = new ArrayList<>(1);
    Enumeration e = NetworkInterface.getNetworkInterfaces();
    if (e == null) {
        return addresses;
    }
    while (e.hasMoreElements()) {
        NetworkInterface n = (NetworkInterface) e.nextElement();
        if (!isValidInterface(n)) {
            continue;
        }
        Enumeration ee = n.getInetAddresses();
        while (ee.hasMoreElements()) {
            InetAddress i = (InetAddress) ee.nextElement();
            if (isValidAddress(i)) {
                addresses.add((Inet4Address) i);
            }
        }
    }
    return addresses;
}

/**
 * 過濾回環(huán)網(wǎng)卡、點對點網(wǎng)卡、非活動網(wǎng)卡、虛擬網(wǎng)卡并要求網(wǎng)卡名字是eth或ens開頭
 *
 * @param ni 網(wǎng)卡
 * @return 如果滿足要求則true,否則false
 */
private static boolean isValidInterface(NetworkInterface ni) throws SocketException {
    return !ni.isLoopback() && !ni.isPointToPoint() && ni.isUp() && !ni.isVirtual()
            && (ni.getName().startsWith("eth") || ni.getName().startsWith("ens"));
}

/**
 * 判斷是否是IPv4,并且內(nèi)網(wǎng)地址并過濾回環(huán)地址.
 */
private static boolean isValidAddress(InetAddress address) {
    return address instanceof Inet4Address && address.isSiteLocalAddress() && !address.isLoopbackAddress();
}

通過訪問外網(wǎng)

當有多個網(wǎng)卡的時候,使用這種方式一般都可以得到想要的IP。甚至不要求外網(wǎng)地址8.8.8.8是可連通的。

private static Optional<Inet4Address> getIpBySocket() throws SocketException {
    try (final DatagramSocket socket = new DatagramSocket()) {
        socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
        if (socket.getLocalAddress() instanceof Inet4Address) {
            return Optional.of((Inet4Address) socket.getLocalAddress());
        }
    } catch (UnknownHostException e) {
        throw new RuntimeException(e);
    }
    return Optional.empty();
}

綜合

在實際使用中,為了兼容更多的場景,項目中一般兼容了以上兩種方式。

public static Optional<Inet4Address> getLocalIp4Address() throws SocketException {
    final List<Inet4Address> ipByNi = getLocalIp4AddressFromNetworkInterface();
    if (ipByNi.isEmpty() || ipByNi.size() > 1) {
        final Optional<Inet4Address> ipBySocketOpt = getIpBySocket();
        if (ipBySocketOpt.isPresent()) {
            return ipBySocketOpt;
        } else {
            return ipByNi.isEmpty() ? Optional.empty() : Optional.of(ipByNi.get(0));
        }
    }
    return Optional.of(ipByNi.get(0));
}

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容