已知网络号和主机数量,合理划分子网及子网掩码

现有网络号为164.146.0.0和主机数量393216,求该网段的子网及子网掩码。

import socket
import struct


def int_to_ip(ip_int:int):
    """
    整数转ip
    :param ip_int:
    :return:
    """
    return socket.inet_ntoa(struct.pack('I', socket.htonl(ip_int)))


def ip_to_int(ip_str:str):
    """
    整数转ip
    :param ip_str:
    :return:
    """
    return socket.ntohl(struct.unpack('I', socket.inet_aton(str(ip_str)))[0])


def calculate_subnet_mask(ip_int:int, num_hosts:int, networks=None):
    """
    根据网络地址和主机数量计算子网掩码.
    ip_int : int : ip地址整数,例如:
    num_hosts : int : 主机数量
    """
    if networks is None:
        networks = []
    i = 0
    # 寻找能够容纳主机数量的最小主机位数
    for x in range(1, 32):
        i = x
        if (pow(2, i + 1) > num_hosts and pow(2, i) <= num_hosts):
            break
    #
    stage = pow(2, i) - 1
    # 按位与运算符:
    # ip_int:2761031680
    # 1010 0100 1001 0010 0000 0000 0000 0000
    # stage:262143
    # 0000 0000 0000 0011 1111 1111 1111 1111
    # cur_num:131072
    # 0000 0000 0000 0010 0000 0000 0000 0000
    # 参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0
    cur_num = ip_int & stage
    while cur_num and i:
        i -= 1
        stage = pow(2, i) - 1
        cur_num = ip_int & stage
    # 下一个网络号
    start_next = ip_int + pow(2, i)
    # 剩余主机数量
    last = num_hosts - pow(2, i)
    net = f'{int_to_ip(ip_int)}/{32 - i}'
    networks.append(net)
    # 如果还有主机数可以分配则进行递归
    if last > 0:
        calculate_subnet_mask(start_next, last, networks)
    return networks


def main():
    """
    主函数
    :return:
    """
    net = '164.146.0.0'
    ip_int = ip_to_int(net)
    num_hosts = 393216
    networks = calculate_subnet_mask(ip_int, num_hosts)
    print(f'net:{net} - hosts:{num_hosts} - networks:{networks}')
    # net:164.146.0.0 - hosts:393216 - networks:['164.146.0.0/15', '164.148.0.0/14']


if __name__ == '__main__':
    main()

以上代码还可以进行优化,并不是最优的方式,比如寻找最小主机位数可以不用每次都从1开始循环,以及可以从输入获取网络号和主机数量等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值