博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IP地址与UInt之间不得不说的故事
阅读量:4487 次
发布时间:2019-06-08

本文共 3872 字,大约阅读时间需要 12 分钟。

IP地址有很多种表示方式,比如原始的二进制,常用的点分十进制。但在涉及到一些有关IP的计算时,这两种表示方式的操作都不是很方便。本文介绍最近在网管项目中使用的uint型ip表示法。使用这种方式,不论是在IP地址的存储,还是计算处理上,都能得到立竿见影的效果。

首先贴出将IP转型为uint的代码:

1     ///  2     /// 将点分十进制格式的IP转换为UInt格式 3     ///  4     /// IP的点分十进制表示 5     /// 
6 private uint GetUIntFromIP(string ipStr) 7 { 8 if (String.IsNullOrEmpty(ipStr) || !IsIPAddress(ipStr)) return 0; 9 string[] ipArr = ipStr.Split('.');10 List
ipIntArr = new List
();11 foreach (var s in ipArr)12 {13 ipIntArr.Add(byte.Parse(s));14 }15 uint result = 0;16 for (int i = 0; i < 4; i++)17 {18 result += (uint)(ipIntArr[i] << (24 - i * 8));19 }20 return result;21 }22 ///
23 /// 验证是否是正确的IP地址24 /// 25 ///
IP字符串26 ///
27 private bool IsIPAddress(string IpStr)28 {29 if (String.IsNullOrEmpty(IpStr)) return false;30 Regex regText = new Regex(@"^((1?\d?\d|(2([0-4]\d|5[0-5])))\.){3}(1?\d?\d|(2([0-4]\d|5[0-5])))$");31 return regText.IsMatch(IpStr);32 }

在上面的GetLongFromIP方法中,首先进行了简单的IP验证,然后将IP地址拆分成byte型的4段。循环中的关键代码 result += (ipUintArr[i] << (24 - i * 8)) 对IP地址的4段分别进行移位操作,再将结果相加。

我们知道,IP地址的最大值表示为:255.255.255.255,也就是其二进制表示的32位全为1。该最大值用上述方法处理后的结果为:4294967295。这正好是C#中uint值的最大值(C#中uint为32位无符号整数)。可以看到,用这种方式将IP地址转换为uint是再合适不过。

理解了上述代码,再将uint格式的IP转换为常见的点分十进制格式,就很简单了,基本上就是上述方法的逆运算:

1     ///  2     /// 将UInt格式的IP转换为点分十进制格式 3     ///  4     ///  5     /// 
6 private string GetIPStrFromUint(uint ip) 7 { 8 byte first = (byte)(ip >> 24); 9 byte second = (byte)((ip - (first << 24)) >> 16);10 byte third = (byte)((ip - (second << 16) - (first << 24)) >> 8);11 byte four = (byte)(ip - (second << 16) - (first << 24) - (third << 8));12 return String.Format("{0}.{1}.{2}.{3}", first, second, third, four);13 }

掌握了IP地址与UInt格式的互转,会给我们在IP地址的处理上带来很多方便。比如常见的某一个网段之间的IP数量(这里的网段用开始IP和结束IP标识):

1     ///  2     /// 获取网段之间的IP数量 3     ///  4     ///  5     ///  6     /// 
7 private uint GetIPCountFromNet(string beginIP,string endIP) 8 { 9 if (String.IsNullOrEmpty(beginIP) || String.IsNullOrEmpty(endIP)) return 0;10 return GetUIntFromIP(endIP) - GetUIntFromIP(beginIP) + 1;11 }

再比如获取两个IP之间包含的IP地址列表:

1     ///  2     /// 获取两个IP之间的IP列表 3     ///  4     ///  5     ///  6     /// 
7 private IEnumerable
GetIPListFromNet(string beginIP, string lastIP) 8 { 9 if (String.IsNullOrEmpty(beginIP) || String.IsNullOrEmpty(lastIP)) yield return null;10 11 uint beginAddress = GetUIntFromIP(beginIP);12 uint lastAddress = GetUIntFromIP(lastIP);13 uint temp = lastAddress - beginAddress;14 for (uint i = 0; i <= temp; i++)15 {16 uint tempAddress = beginAddress + i;17 //将UInt格式的IP转换为点分十进制表示18 string ipAddress = GetIPStrFromUint(tempAddress);19 yield return ipAddress;20 }21 }

另外,如果要查询一个IP地址是否属于某个网段,转换成UInt格式以后非常方便。而传统的Sql不会智能到可以判断 begin_ip<='xxx.xxx.xxx.xxx'<=end_ip。当然,也可以利用一些Sql内置函数实现此功能,只是相比本文提到的UInt方式,相对繁琐:

select count(id) from ip_net where     right('000' + parsename('xxx.xxx.xxx.xxx',4),3)     + right('000' + parsename('xxx.xxx.xxx.xxx',3),3)     + right('000' + parsename('xxx.xxx.xxx.xxx',2),3)     + right('000' + parsename('xxx.xxx.xxx.xxx',1),3)between     right('000' + parsename(begin_ip,4),3)     + right('000' + parsename(begin_ip,3),3)     + right('000' + parsename(begin_ip,2),3)     + right('000' + parsename(begin_ip,1),3)and    right('000' + parsename(end_ip,4),3)     + right('000' + parsename(end_ip,3),3)     + right('000' + parsename(end_ip,2),3)     + right('000' + parsename(end_ip,1),3)

转载于:https://www.cnblogs.com/mcmurphy/archive/2012/10/31/2748276.html

你可能感兴趣的文章
L1-047 装睡
查看>>
雷林鹏分享:jQuery EasyUI 菜单与按钮 - 创建链接按钮
查看>>
Apache Traffic Server服务搭建
查看>>
poj1990两个树状数组
查看>>
学习python-day1
查看>>
Zend_Db_Table->insert ()和zend_db_adapter::insert方法返回值不同
查看>>
递归问题
查看>>
Hyperledger下子项目
查看>>
Linq-查询上一条下一条
查看>>
常见前端开发的题目,可能对你有用
查看>>
BeautifulSoap库入门
查看>>
乐观锁与悲观锁
查看>>
Codeforces Round #328 (Div. 2)D. Super M 虚树直径
查看>>
Java判断是否为移动端
查看>>
chromedriver下载链接以及对应版本
查看>>
[SimplePlayer] 6. 音频同步
查看>>
把一个SVN项目的目录结构 导入到另外一个空白的SVN项目里
查看>>
Android之Adapter用法总结-(转)
查看>>
总结列表显示ListView知识点
查看>>
android 教程实例系列
查看>>