Java如何實(shí)現(xiàn)CIDR轉(zhuǎn)IP段
一、CIDR 的核心概念
CIDR(Classless Inter-Domain Routing,無類別域間路由)是一種用于高效分配和管理 IP 地址的網(wǎng)絡(luò)編址方法。它取代了傳統(tǒng)的 IP 地址分類(A/B/C 類),通過靈活的網(wǎng)絡(luò)前綴長度(子網(wǎng)掩碼)實(shí)現(xiàn)更精細(xì)的地址劃分和路由聚合,顯著提高了 IP 地址的利用率,并減少了路由表規(guī)模。
1. 傳統(tǒng) IP 分類的局限性
A/B/C 類地址:傳統(tǒng)方式將 IP 地址劃分為固定類別(如 A 類:/8,B 類:/16,C 類:/24)。
問題:地址分配不靈活。例如,一個(gè)需要 500 個(gè) IP 的機(jī)構(gòu)必須申請一個(gè) B 類地址(65,536 個(gè) IP),造成大量浪費(fèi)。
2. CIDR 的解決方案
無類別劃分:不再依賴固定類別,允許任意長度的網(wǎng)絡(luò)前綴(如 /17、/22)。
格式:IP地址/前綴長度(例如 192.168.1.0/24),其中:
前綴長度:表示網(wǎng)絡(luò)部分的位數(shù)(如 /24 表示前 24 位是網(wǎng)絡(luò)地址)。
主機(jī)部分:剩余位數(shù)用于主機(jī)地址(如 /24 的主機(jī)部分有 8 位,支持 256 個(gè) IP)。
CIDR 是現(xiàn)代互聯(lián)網(wǎng)的基礎(chǔ)技術(shù),解決了傳統(tǒng) IP 分類的僵化問題,通過靈活的網(wǎng)絡(luò)前綴管理和路由聚合,顯著提升了 IP 地址的使用效率,是網(wǎng)絡(luò)規(guī)劃和運(yùn)維的核心工具。
二、實(shí)現(xiàn)原理分析
那如何用Java來實(shí)現(xiàn) “CIDR轉(zhuǎn)IP段” 呢?
2.1 將IP地址和掩碼分開處理
比如輸入的字符串需要拆分成IP部分和掩碼位數(shù)。比如"221.236.192.0/21"需要拆分成IP地址221.236.192.0和掩碼21。
2.2 將IP地址轉(zhuǎn)換為32位的整數(shù)形式
例如,將每個(gè)部分(四個(gè)八位組)轉(zhuǎn)換為二進(jìn)制,拼接成一個(gè)32位的整數(shù)。比如,221.236.192.0轉(zhuǎn)換成二進(jìn)制后,再計(jì)算其整數(shù)形式。
2.3 根據(jù)掩碼位數(shù)計(jì)算子網(wǎng)掩碼
掩碼21位的話,子網(wǎng)掩碼的前21位是1,后面是0??梢杂梦贿\(yùn)算來生成這個(gè)掩碼。例如,子網(wǎng)掩碼的整數(shù)形式是0xFFFFFFFF << (32 - 21),然后和0xFFFFFFFF進(jìn)行與操作,確保高位正確。
網(wǎng)絡(luò)地址可以通過將IP地址的整數(shù)形式與子網(wǎng)掩碼進(jìn)行按位與運(yùn)算得到。起始IP就是這個(gè)網(wǎng)絡(luò)地址。
廣播地址是網(wǎng)絡(luò)地址的主機(jī)部分全置1。可以通過將網(wǎng)絡(luò)地址與子網(wǎng)掩碼的反碼按位或得到。結(jié)束IP就是廣播地址。
然后需要將這兩個(gè)整數(shù)形式的起始和結(jié)束IP轉(zhuǎn)換回點(diǎn)分十進(jìn)制的字符串形式。比如,將整數(shù)拆分成四個(gè)八位組,每個(gè)部分轉(zhuǎn)換成十進(jìn)制數(shù),拼接成IP字符串。
2.4 程序方法實(shí)現(xiàn)步驟
可能需要注意的細(xì)節(jié):
輸入驗(yàn)證:確保CIDR格式正確,IP各部分在0-255之間,掩碼位數(shù)在0-32之間。
處理IP轉(zhuǎn)換時(shí)的整數(shù)溢出問題,Java中應(yīng)該使用long類型來處理32位無符號整數(shù),避免符號位的問題。
轉(zhuǎn)換IP地址時(shí),特別是處理每個(gè)八位組的時(shí)候,要注意移位和位掩碼的正確使用。
測試邊界情況,比如掩碼為32時(shí),起始和結(jié)束IP相同;掩碼為0時(shí),整個(gè)地址范圍是0.0.0.0到255.255.255.255。
現(xiàn)在,具體步驟:
拆分輸入字符串為IP和掩碼部分。
String[] parts = cidr.split("/"); String ip = parts[0]; int prefix = Integer.parseInt(parts[1]);
將IP地址轉(zhuǎn)換為32位整數(shù)(使用long避免符號問題)。
String[] octets = ip.split("\\."); long ipLong = (Long.parseLong(octets[0]) << 24) | (Long.parseLong(octets[1]) << 16) | (Long.parseLong(octets[2]) << 8) | Long.parseLong(octets[3]);
計(jì)算子網(wǎng)掩碼。
long mask = 0xFFFFFFFFL << (32 - prefix);
計(jì)算網(wǎng)絡(luò)地址(起始IP)。
long startIp = ipLong & mask;
計(jì)算廣播地址(結(jié)束IP)。
long endIp = startIp | (~mask);
但是,這里要注意,Java中的位運(yùn)算~會反轉(zhuǎn)所有64位,所以需要用0xFFFFFFFFL來掩碼,只保留低32位:
long endIp = startIp | (~mask & 0xFFFFFFFFL);
將startIp和endIp轉(zhuǎn)換為點(diǎn)分十進(jìn)制字符串。
private static String longToIp(long ip) { return String.format("%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); }
封裝結(jié)果到Map中。
Map<String, String> result = new HashMap<>(); result.put("start", longToIp(startIp)); result.put("end", longToIp(endIp));
然后需要考慮輸入驗(yàn)證,比如檢查parts的長度是否為2,prefix是否在0到32之間,IP是否有四個(gè)八位組,每個(gè)數(shù)值是否在0-255之間。
綜上,編寫的方法應(yīng)該包括:
- 輸入驗(yàn)證,確保CIDR格式正確,IP各段有效,掩碼有效。
- 轉(zhuǎn)換IP為長整型。
- 計(jì)算子網(wǎng)掩碼、網(wǎng)絡(luò)地址和廣播地址。
- 轉(zhuǎn)換回IP字符串。
- 封裝結(jié)果到Map中。
可能還需要處理一些異常,比如NumberFormatException,這時(shí)候可能需要拋出IllegalArgumentException,或者返回null,但用戶可能需要一個(gè)健壯的方法。在示例代碼中,可能簡化處理,假設(shè)輸入是正確的,或者添加必要的驗(yàn)證。
現(xiàn)在,根據(jù)以上分析,編寫Java代碼。
三、Java代碼完整實(shí)現(xiàn)
以下是實(shí)現(xiàn)該功能的 Java 方法,包含詳細(xì)注釋和輸入驗(yàn)證:
import java.util.HashMap; import java.util.Map; public class CidrConverter { public static Map<String, String> splitCidr(String cidr) { Map<String, String> result = new HashMap<>(); // 驗(yàn)證輸入格式(例如 "221.236.192.0/21") if (!cidr.matches("^(\\d+\\.){3}\\d+/\\d+$")) { throw new IllegalArgumentException("Invalid CIDR format"); } String[] parts = cidr.split("/"); String ipAddress = parts[0]; int prefixLength = Integer.parseInt(parts[1]); // 驗(yàn)證子網(wǎng)掩碼位數(shù) if (prefixLength < 0 || prefixLength > 32) { throw new IllegalArgumentException("Invalid prefix length"); } // 將IP地址轉(zhuǎn)換為32位整數(shù)(用long避免符號問題) String[] ipOctets = ipAddress.split("\\."); if (ipOctets.length != 4) { throw new IllegalArgumentException("Invalid IP address"); } long ipLong = 0; for (int i = 0; i < 4; i++) { int octet = Integer.parseInt(ipOctets[i]); if (octet < 0 || octet > 255) { throw new IllegalArgumentException("Invalid IP octet"); } ipLong |= (long) octet << (24 - (8 * i)); } // 計(jì)算子網(wǎng)掩碼 long mask = 0xFFFFFFFFL << (32 - prefixLength); // 計(jì)算起始IP(網(wǎng)絡(luò)地址) long startIp = ipLong & mask; // 計(jì)算結(jié)束IP(廣播地址) long endIp = startIp | (~mask & 0xFFFFFFFFL); // 轉(zhuǎn)換為點(diǎn)分十進(jìn)制字符串 result.put("start", longToIp(startIp)); result.put("end", longToIp(endIp)); return result; } // 將32位整數(shù)轉(zhuǎn)換為IP字符串 private static String longToIp(long ip) { return ((ip >> 24) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + (ip & 0xFF); } // 測試用例 public static void main(String[] args) { String cidr = "221.236.192.0/21"; Map<String, String> ipRange = splitCidr(cidr); System.out.println("起始IP: " + ipRange.get("start")); // 221.236.192.0 System.out.println("結(jié)束IP: " + ipRange.get("end")); // 221.236.199.255 } }
代碼說明
1.輸入驗(yàn)證
- 使用正則表達(dá)式檢查 CIDR 格式合法性
- 驗(yàn)證子網(wǎng)掩碼位數(shù)范圍 (0-32)
- 檢查 IP 地址的四個(gè)八位組是否合法 (0-255)
2.核心計(jì)算邏輯
- 將 IP 地址轉(zhuǎn)換為 32 位整數(shù)(使用 long 避免符號問題)
- 通過位運(yùn)算計(jì)算子網(wǎng)掩碼、網(wǎng)絡(luò)地址和廣播地址
3.示例測試
輸入 221.236.192.0/21 時(shí),輸出:
起始IP: 221.236.192.0
結(jié)束IP: 221.236.199.255
關(guān)鍵公式
- 子網(wǎng)掩碼:mask = 0xFFFFFFFFL << (32 - prefixLength)
- 網(wǎng)絡(luò)地址:startIp = ipLong & mask
- 廣播地址:endIp = startIp | (~mask & 0xFFFFFFFFL)
注意事項(xiàng)
- 輸入合法性:需確保 CIDR 格式正確(例如 192.168.1.0/24)
- 性能優(yōu)化:位運(yùn)算直接操作內(nèi)存,效率極高
- 大地址處理:使用 long 避免 int 的符號問題
到此這篇關(guān)于Java如何實(shí)現(xiàn)CIDR轉(zhuǎn)IP段的文章就介紹到這了,更多相關(guān)Java CIDR轉(zhuǎn)IP段內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解SpringBoot統(tǒng)一響應(yīng)體解決方案
這篇文章主要介紹了詳解SpringBoot統(tǒng)一響應(yīng)體解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Spring MVC Controller返回值及異常的統(tǒng)一處理方法
這篇文章主要給大家介紹了關(guān)于Spring MVC Controller返回值及異常的統(tǒng)一處理方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Spring MVC具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法
遇到了個(gè)問題,同一天可以輸入多個(gè)時(shí)間段,但是每個(gè)時(shí)間段的時(shí)間不能出現(xiàn)重疊,這不就是判斷數(shù)據(jù)返回是否有重疊的變種嗎,所以本文給大家介紹了Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法,需要的朋友可以參考下2024-07-07計(jì)算Java數(shù)組長度函數(shù)的方法以及代碼分析
在本篇內(nèi)容里,小編給大家整理了關(guān)于計(jì)算Java數(shù)組長度函數(shù)的方法以及代碼分析內(nèi)容,有興趣的朋友么可以學(xué)習(xí)參考下。2022-11-11java中Redisson的看門狗機(jī)制的實(shí)現(xiàn)
本文主要介紹了java中Redisson的看門狗機(jī)制的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Java實(shí)現(xiàn)多線程大批量同步數(shù)據(jù)(分頁)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多線程大批量同步數(shù)據(jù)(分頁),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08