现有网络号为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开始循环,以及可以从输入获取网络号和主机数量等。