算法与设计模式系列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
}

原文地址:https://www.cnblogs.com/liaojiafa/p/6613983.html