算法与设计模式系列2之实现子网掩码的从数字到常用格式的转换
preface
因为linux系统信息采集的需要,需要把数字类型的掩码转换为255.255.0.0这样的格式,尽管python官网提供了IPy这样的模块可以处理这样的事情,,但是本人懒得安装了,所以自己写了 一个算法来做,有兴趣的同学可以参考下。目前还未测试出bug,如果有问题请随时联系本人邮箱18500777133@sina.cn
Python版本
def calc_netmask(netmask):
'''
计算子网掩码,由数字类型转为xx.xxx.xx.xx
算法是这样的: 得到的数字先除以8,得到的商就是有多少个255,余数就需要再计算,余数等于1,那么最后一位子网眼码就是2**(8-1),8是一段子网眼码长度,
为8个1,1111111,二进制计算。最后一段眼码计算方式如下:
余数为1,即2**7,
余数为2,即2**7+2**6
余数为3,即2**7+2**6+2**5
依次类推
:param netmask:
:return:
'''
if isinstance(netmask,int):
factor,remainder =netmask.__divmod__(8)
mi = 8 - remainder # 计算这个数字的幂
last_mask = 0
while mi <= 7: # 判断掩码长度是否超过了7,超过了长度跳出循环,因为掩码的长度最多是8.
last_mask = 2**mi + last_mask
mi=mi+1
if factor == 1 and last_mask == 0 : # 意味着是8位的子网掩码
return_netmask = "%s%s"%(factor*'255.','0.0.0')
elif (factor == 1 and last_mask != 0 ) : #意味着8-24之间的子网掩码
last_mask = '%s.'%last_mask
return_netmask = "%s%s%s"%(factor*'255.',last_mask,'0.0')
elif (factor == 2 and last_mask == 0): #意味着16位整的子网掩码
return_netmask = "%s0.0"%(factor*'255.')
elif( factor == 3 and last_mask == 0 ): # 意味着24位整的掩码
return_netmask = "%s%s"%(factor*'255.','0')
elif( factor == 3 and last_mask != 0 ): #意味着24-32之间的子网掩码
return_netmask = "%s%s"%(factor*'255.',last_mask)
elif (factor == 2 and last_mask != 0): # 意味着16-24位之间子网掩码
return_netmask = "%s%s.%s"%(factor*'255.',last_mask,'0')
elif factor == 4: # 意味着4个255
return_netmask = "%s255"%((factor-1)*'255.')
elif factor == 0: # 小于8位的掩码
return_netmask = "%s.0.0.0"%(last_mask)
return return_netmask
else:
return False
for i in range(0,33):
print(i,calc_netmask(i))
打印结果如下:
第一列数字是掩码的数字,第二列是转换后掩码的格式
0 0.0.0.0
1 128.0.0.0
2 192.0.0.0
3 224.0.0.0
4 240.0.0.0
5 248.0.0.0
6 252.0.0.0
7 254.0.0.0
8 255.0.0.0
9 255.128.0.0
10 255.192.0.0
11 255.224.0.0
12 255.240.0.0
13 255.248.0.0
14 255.252.0.0
15 255.254.0.0
16 255.255.0.0
17 255.255.128.0
18 255.255.192.0
19 255.255.224.0
20 255.255.240.0
21 255.255.248.0
22 255.255.252.0
23 255.255.254.0
24 255.255.255.0
25 255.255.255.128
26 255.255.255.192
27 255.255.255.224
28 255.255.255.240
29 255.255.255.248
30 255.255.255.252
31 255.255.255.254
32 255.255.255.255
go版
import (
"math"
"fmt"
)
func calcNetmask(netmask int) (return_netmask string) {
/*
计算子网掩码,由数字类型转为xx.xxx.xx.xx
算法是这样的: 得到的数字先除以8,得到的商就是有多少个255,余数就需要再计算,余数等于1,那么最后一位子网眼码就是2**(8-1),8是一段子网眼码长度,
为8个1,1111111,二进制计算。最后一段眼码计算方式如下:
余数为1,即2**7,
余数为2,即2**7+2**6
余数为3,即2**7+2**6+2**5
依次类推
:param netmask: tmp netmask
:return:
*/
factor := netmask / 8 // 商
remainder := netmask % 8 // 余数
mi := 8 - remainder // 计算这个数字的幂
var tmp_last_mask float64
for mi <= 7 { // 判断掩码长度是否超过了7,超过了长度跳出循环,因为掩码的长度最多是8.
tmp_last_mask = math.Pow(float64(2), float64(mi)) + tmp_last_mask
mi = mi + 1
}
last_mask := int(tmp_last_mask)
switch {
case factor == 1 && last_mask == 0: // 意味着是8位的子网掩码
return_netmask = fmt.Sprintf("%s%s", addStr(factor, "255."), "0.0.0")
case (factor == 1 && last_mask != 0): //意味着8-24之间的子网掩码
return_netmask = fmt.Sprintf("%s%d.%s", addStr(factor, "255."), last_mask, "0.0")
case (factor == 2 && last_mask == 0): //意味着16位整的子网掩码
return_netmask = fmt.Sprintf("%s0.0", addStr(factor, "255."))
case (factor == 3 && last_mask == 0): // 意味着24位整的掩码
return_netmask = fmt.Sprintf("%s%s", addStr(factor, "255."), "0")
case (factor == 3 && last_mask != 0): // 意味着24-32之间的子网掩码
return_netmask = fmt.Sprintf("%s%d", addStr(factor, "255."), last_mask)
case (factor == 2 && last_mask != 0): // 意味着16-24位之间子网掩码
return_netmask = fmt.Sprintf("%s%d.%s", addStr(factor, "255."), last_mask, "0")
case factor == 4: // 意味着4个255
return_netmask = fmt.Sprintf("%s255", addStr(factor-1, "255."))
case factor == 0: // 小于8位的掩码
return_netmask = fmt.Sprintf("%d.0.0.0", last_mask)
}
return return_netmask
}