将 CIDR 表示法转换为 IP 范围
Convert CIDR notation into IP range
我们正在使用 GeoLite2 数据库来执行 IP -> country 查询。出于性能原因,我们希望导入 CSV 并将其转换为我们自己的格式。
CSV 表示如下:
5.39.40.96/27,3017382,3017382,,0,0
5.39.40.128/28,3017382,3017382,,0,0
5.39.40.144/28,2635167,3017382,,0,0
5.39.40.160/27,3017382,3017382,,0,0
5.39.40.192/26,3017382,3017382,,0,0
5.39.41.0/25,3017382,3017382,,0,0
5.39.41.128/26,3017382,3017382,,0,0
5.39.41.192/26,2635167,3017382,,0,0
5.39.42.0/24,3017382,3017382,,0,0
5.39.43.0/25,3017382,3017382,,0,0
因此我们需要将 CIDR 表示法(示例:5.39.40.96/27
)转换为 IP 地址范围。 (从 IP - 到 IP)
如何在 C# 中完成此操作?
注意: 这不是 this question 的副本,因为我问的是 C# 实现而不是 Java。
这是一种处理它的方法,无需使用任何库函数来弄清楚发生了什么,并在以后有人需要用其他语言实现它时提供帮助。
代码首先将 CIDR 转换为 32 位数字,然后创建掩码以确定起始地址,使用掩码的倒数确定结束地址,然后转换回 CIDR 格式。
请注意,没有错误检测,因此输入必须采用 a.b.c.d/m 格式。
IP 地址的转换只是使用移位将大端格式 (AABBCCDD) 的四个八位字节简单串联起来。
掩码表示从最高有效位开始有多少位是固定的,这意味着 32 是单个 IP 范围,0 将是整个 IP 范围。因此我们可以采用所有位设置的掩码并将其左移 32-maskbits
以确定实际掩码。
如果我们将 maskbits
位设置为零,我们将获得范围的开头,因此我们将 IP 与掩码位进行 AND 运算。如果我们将这些位设置为 1,我们就会到达范围的末尾,因此我们将与掩码的取反位进行 OR。
以 CIDR 格式打印 IP 地址也很简单:只需将 32 位值分成八位字节,然后用点分隔写入即可。
using System;
namespace CSTests
{
class Program
{
static string toip(uint ip)
{
return String.Format("{0}.{1}.{2}.{3}", ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
}
static void Main(string[] args)
{
string IP = "5.39.40.96/27";
string[] parts = IP.Split('.', '/');
uint ipnum = (Convert.ToUInt32(parts[0]) << 24) |
(Convert.ToUInt32(parts[1]) << 16) |
(Convert.ToUInt32(parts[2]) << 8) |
Convert.ToUInt32(parts[3]);
int maskbits = Convert.ToInt32(parts[4]);
uint mask = 0xffffffff;
mask <<= (32 - maskbits);
uint ipstart = ipnum & mask;
uint ipend = ipnum | (mask ^ 0xffffffff);
Console.WriteLine(toip(ipstart) + " - " + toip(ipend));
}
}
}
输出:
5.39.40.96 - 5.39.40.127
Sami Kuhmonen,这是非常好的代码并且经过认真简化。我注意到它 return 是网络 ID 和广播。但是,对于那些希望 return 可用地址 space 的人。只需将起始 IP 加一并从结束 IP 减一。
toip(ipstart + 1) + " - " + toip(ipend -1);
我们正在使用 GeoLite2 数据库来执行 IP -> country 查询。出于性能原因,我们希望导入 CSV 并将其转换为我们自己的格式。
CSV 表示如下:
5.39.40.96/27,3017382,3017382,,0,0
5.39.40.128/28,3017382,3017382,,0,0
5.39.40.144/28,2635167,3017382,,0,0
5.39.40.160/27,3017382,3017382,,0,0
5.39.40.192/26,3017382,3017382,,0,0
5.39.41.0/25,3017382,3017382,,0,0
5.39.41.128/26,3017382,3017382,,0,0
5.39.41.192/26,2635167,3017382,,0,0
5.39.42.0/24,3017382,3017382,,0,0
5.39.43.0/25,3017382,3017382,,0,0
因此我们需要将 CIDR 表示法(示例:5.39.40.96/27
)转换为 IP 地址范围。 (从 IP - 到 IP)
如何在 C# 中完成此操作?
注意: 这不是 this question 的副本,因为我问的是 C# 实现而不是 Java。
这是一种处理它的方法,无需使用任何库函数来弄清楚发生了什么,并在以后有人需要用其他语言实现它时提供帮助。
代码首先将 CIDR 转换为 32 位数字,然后创建掩码以确定起始地址,使用掩码的倒数确定结束地址,然后转换回 CIDR 格式。
请注意,没有错误检测,因此输入必须采用 a.b.c.d/m 格式。
IP 地址的转换只是使用移位将大端格式 (AABBCCDD) 的四个八位字节简单串联起来。
掩码表示从最高有效位开始有多少位是固定的,这意味着 32 是单个 IP 范围,0 将是整个 IP 范围。因此我们可以采用所有位设置的掩码并将其左移 32-maskbits
以确定实际掩码。
如果我们将 maskbits
位设置为零,我们将获得范围的开头,因此我们将 IP 与掩码位进行 AND 运算。如果我们将这些位设置为 1,我们就会到达范围的末尾,因此我们将与掩码的取反位进行 OR。
以 CIDR 格式打印 IP 地址也很简单:只需将 32 位值分成八位字节,然后用点分隔写入即可。
using System;
namespace CSTests
{
class Program
{
static string toip(uint ip)
{
return String.Format("{0}.{1}.{2}.{3}", ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
}
static void Main(string[] args)
{
string IP = "5.39.40.96/27";
string[] parts = IP.Split('.', '/');
uint ipnum = (Convert.ToUInt32(parts[0]) << 24) |
(Convert.ToUInt32(parts[1]) << 16) |
(Convert.ToUInt32(parts[2]) << 8) |
Convert.ToUInt32(parts[3]);
int maskbits = Convert.ToInt32(parts[4]);
uint mask = 0xffffffff;
mask <<= (32 - maskbits);
uint ipstart = ipnum & mask;
uint ipend = ipnum | (mask ^ 0xffffffff);
Console.WriteLine(toip(ipstart) + " - " + toip(ipend));
}
}
}
输出:
5.39.40.96 - 5.39.40.127
Sami Kuhmonen,这是非常好的代码并且经过认真简化。我注意到它 return 是网络 ID 和广播。但是,对于那些希望 return 可用地址 space 的人。只需将起始 IP 加一并从结束 IP 减一。
toip(ipstart + 1) + " - " + toip(ipend -1);