首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 判斷本機 IP 地址類型 (A/B/C/D/E 類) 與 InetAddress 實戰

     編輯:Java 程式設計入門

IP 地址分類基礎 (有類別路由 CIDR 前標準)

類別首位元組範圍二進位開頭網路數主機數/網路用途
A1 - 1260xxxxxxx12616,777,214大型網路
B128 - 19110xxxxxx16,38465,534中型網路
C192 - 223110xxxxx2,097,152254小型網路
D224 - 2391110xxxxN/AN/A多播
E240 - 2551111xxxxN/AN/A保留/實驗

特殊保留:127.x.x.x (回環)、0.0.0.0 (本網路)、255.255.255.255 (廣播)、169.254.x.x (APIPA)、私有網段 (10.x、172.16-31.x、192.168.x)

InetAddress 核心 API


import java.net.*;

public class IpAnalyzer {

    public static void main(String[] args) throws Exception {
        // 1. 獲取本機所有 IP
        System.out.println("=== 本機 IP ===");
        Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface ni = interfaces.nextElement();
            // 過濾回環、關閉、虛擬介面
            if (ni.isLoopback() || !ni.isUp() || ni.isVirtual()) continue;
            
            Enumeration addresses = ni.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress ia = addresses.nextElement();
                if (ia instanceof Inet4Address) { // 只看 IPv4
                    System.out.printf("介面: %-10s IP: %-15s 類別: %s%n", 
                        ni.getName(), ia.getHostAddress(), getIpClass(ia));
                }
            }
        }

        // 2. 域名解析
        System.out.println("\n=== 域名解析 ===");
        InetAddress[] google = InetAddress.getAllByName("www.google.com");
        for (InetAddress ia : google) {
            System.out.println(ia.getHostAddress() + " -> " + getIpClass(ia));
        }

        // 3. byte[] 處理陷阱
        InetAddress local = InetAddress.getByName("192.168.1.100");
        byte[] bytes = local.getAddress(); // 有號 byte (-128~127)
        System.out.println("\n=== byte[] 處理 ===");
        for (byte b : bytes) {
            // 錯誤:直接印 b 會出現負數
            // 正確:轉無號 int
            int unsigned = b & 0xFF;
            System.out.print(unsigned + " ");
        }
    }

    /**
     * 判斷 IPv4 地址類別 (基於首位元組)
     */
    public static String getIpClass(InetAddress ia) {
        if (!(ia instanceof Inet4Address)) return "IPv6";
        
        byte[] bytes = ia.getAddress();
        int firstOctet = bytes[0] & 0xFF; // 關鍵:無號轉換
        
        if (firstOctet == 127) return "Loopback (A類保留)";
        if (firstOctet == 0) return "Current Network";
        if (firstOctet >= 240) return "E 類 (保留)";
        if (firstOctet >= 224) return "D 類 (多播)";
        if (firstOctet >= 192) return "C 類";
        if (firstOctet >= 128) return "B 類";
        if (firstOctet >= 1) return "A 類";
        return "Unknown";
    }
}

關鍵技術點:有號 byte 與無號轉換


// Java byte 為有號 (-128 ~ 127)
// IP 位元組為無號 (0 ~ 255)
// 必須用 & 0xFF 或 Byte.toUnsignedInt() 轉換

byte b = (byte) 200; // 實際位元模式 11001000
int signed = b;      // -56 (錯誤解讀)
int unsigned = b & 0xFF; // 200 (正確)
int unsigned2 = Byte.toUnsignedInt(b); // Java 8+ 200 (正確)

// 完整 IP 轉長整數 (用於比較/存儲)
public static long ipToLong(InetAddress ia) {
    byte[] bytes = ia.getAddress();
    long result = 0;
    for (byte b : bytes) {
        result = (result << 8) | (b & 0xFF);
    }
    return result;
}

// 長整數轉 IP 字串
public static String longToIp(long ip) {
    return ((ip >> 24) & 0xFF) + "." +
           ((ip >> 16) & 0xFF) + "." +
           ((ip >> 8) & 0xFF) + "." +
           (ip & 0xFF);
}

實戰工具類:IP 範圍判斷、私有/公網識別


import java.net.*;
import java.util.*;

public class IpUtils {

    // 私有網段 CIDR
    private static final List PRIVATE_RANGES = Arrays.asList(
        new Inet4AddressRange("10.0.0.0", "10.255.255.255"),      // 10/8
        new Inet4AddressRange("172.16.0.0", "172.31.255.255"),    // 172.16/12
        new Inet4AddressRange("192.168.0.0", "192.168.255.255")   // 192.168/16
    );

    // 其他保留段
    private static final List RESERVED_RANGES = Arrays.asList(
        new Inet4AddressRange("127.0.0.0", "127.255.255.255"),    // 回環
        new Inet4AddressRange("169.254.0.0", "169.254.255.255"),  // APIPA
        new Inet4AddressRange("224.0.0.0", "239.255.255.255"),    // 多播 D類
        new Inet4AddressRange("240.0.0.0", "255.255.255.255")     // 保留 E類
    );

    public static boolean isPrivate(InetAddress ia) {
        if (!(ia instanceof Inet4Address)) return false;
        long ip = ipToLong(ia);
        return PRIVATE_RANGES.stream().anyMatch(r -> r.contains(ip));
    }

    public static boolean isLoopback(InetAddress ia) {
        return ia.isLoopbackAddress() || isInRange(ia, "127.0.0.0", "127.255.255.255");
    }

    public static boolean isPublic(InetAddress ia) {
        return !(isPrivate(ia) || isLoopback(ia) || ia.isMulticastAddress() || ia.isAnyLocalAddress());
    }

    public static String getIpType(InetAddress ia) {
        if (ia.isLoopbackAddress()) return "Loopback";
        if (ia.isMulticastAddress()) return "Multicast (D類)";
        if (ia.isAnyLocalAddress()) return "Unspecified (0.0.0.0)";
        if (isPrivate(ia)) return "Private (RFC1918)";
        if (ia instanceof Inet4Address) return "Public IPv4 (" + getIpClass(ia) + ")";
        return "IPv6";
    }

    // 內部範圍檢查輔助類
    static class Inet4AddressRange {
        final long start, end;
        Inet4AddressRange(String startIp, String endIp) {
            this.start = ipToLong(parseIp(startIp));
            this.end = ipToLong(parseIp(endIp));
        }
        boolean contains(long ip) { return ip >= start && ip <= end; }
    }

    static InetAddress parseIp(String ip) {
        try { return InetAddress.getByName(ip); }
        catch (UnknownHostException e) { throw new IllegalArgumentException(e); }
    }
}

常見應用場景

  1. 存取控制:僅允許私有網段/IP 白名單存取管理介面
  2. 日誌分析:區分內部/外部流量、識別代理真實 IP
  3. 服務發現:註冊中心過濾非業務網卡 IP
  4. 安全審計:檢測非預期公網 IP 連線
  5. 網路診斷:自動偵測介面、顯示分類資訊

現代替代方案

  • java.net.NetworkInterface:枚舉網卡、獲取介面屬性 (MTU、MAC、MTU)
  • com.google.common.net.InetAddresses (Guava):isInetAddress(), forString(), toAddrString()
  • org.apache.commons.net.util.SubnetUtils:CIDR 範圍判斷 new SubnetUtils("192.168.1.0/24").getInfo().isInRange(ip)
  • IPv6 支援:Inet6Address、NetworkInterface.getInetAddresses() 同時返回 v4/v6
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved