要求实现遍历一个指定的IP范围(例如:66.16.1.1到66.16.254.254),每批次处理一定数量的IP(这里设置为50个),并尝试对每个IP进行ping操作。如果ping成功,将IP地址写入到指定的输出文件中
共分两步:1、统计ping通的IP。2、计算每个小IP段是多少个IP
一、单线程处理方式
#单线程
import subprocess
from ftplib import all_errors
# 设置IP范围和输出文件路径
start_ip = "66.16.1.1"
end_ip = "66.16.254.254"
output_file = "ping_results.txt"
# 辅助函数,将IP地址转换为整数
def ip_to_int(ip):
return int("".join([format(int(x), '08b') for x in ip.split(".")]), 2)
# 辅助函数,将整数转换回IP地址格式
def int_to_ip(num):
return ".".join([str(num >> (i << 3) & 0xFF) for i in range(3, -1, -1)])
# 将IP地址转换为整数以便进行范围检查
start = int(ip_to_int(start_ip))
end = int(ip_to_int(end_ip))
# 确保输出文件存在
with open(output_file, 'w') as f:
f.write("# IP Range: 66.16.1.1 to 66.16.254.254\n")
# 遍历IP范围
current = start
while current <= end:
ip = int_to_ip(current)
try:
# 尝试ping IP
response = subprocess.run(["ping", "-n", "1", ip], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=3)
if response.returncode == 0:
print('ping',ip,'成功')
# Ping成功,写入文件
with open(output_file, 'a') as f:
f.write(f"{current}: {ip}\n")
except Exception as e:
print(f"inallyError pinging {ip}: {e}")
# 每50个IP写入一次
if (current - start) % 50 == 0 and current != start:
print(f"Processed {(current - start) // 50 * 50} IPs")
# 准备下一个IP
current += 1
print("IP range ping completed.")
或
#单线程
import subprocess
from ftplib import all_errors
import os
# 设置IP范围和输出文件路径
start_ip = "66.16.10.1"
end_ip = "66.16.254.254"
output_file = "ping_results.txt"
count_file = r'ping_count.txt' #汇总日志文件
# 辅助函数,将IP地址转换为整数
def ip_to_int(ip):
return int("".join([format(int(x), '08b') for x in ip.split(".")]), 2)
# 辅助函数,将整数转换回IP地址格式
def int_to_ip(num):
return ".".join([str(num >> (i << 3) & 0xFF) for i in range(3, -1, -1)])
# 将IP地址转换为整数以便进行范围检查
start = int(ip_to_int(start_ip))
end = int(ip_to_int(end_ip))
# 确保输出文件存在
with open(output_file, 'w', encoding='utf-8') as f:
f.write("# IP Range: 66.16.19.1 to 66.16.254.254\n")
with open(count_file, 'w', encoding='utf-8') as f:
f.write("#每个网段可ping通个数:网段,可ping通数量\n")
k = int(int_to_ip(start).split('.')[2])
count=0
# 遍历IP范围
current = start
while current <= end:
ip = int_to_ip(current)
last = int(int_to_ip(current).split('.')[2])
if k == last - 1:
print(f"网段{k}中,有{count}个可ping通的ip")
#以下两个注释应至少解开一个,以便有本地存储的汇总日志
#注释以下两行,可通ping_results.txt中不写汇总
# with open(output_file, 'a', encoding='utf-8') as f:
# f.write(f"网段{k}中,有{count}个可ping通的ip\n")
#注释以下两行,不写入ping_count.txt文件
with open(count_file, 'a', encoding='utf-8') as f:
f.write(f"{k},{count}\n")
k = last
count = 0
try:
# 尝试ping IP
response = subprocess.run(["ping", "-c", "1", ip], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if response.returncode == 0:
print(ip, '成功')
# Ping成功,写入文件
with open(output_file, 'a', encoding='utf-8') as f:
f.write(f"{current}: {ip}\n")
count += 1
else:
print(ip, "失败")
except Exception as e:
print(f"Error pinging {ip}: {e}")
# 每50个IP写入一次
if (current - start) % 50 == 0 and current != start:
print(f"Processed {(current - start) // 50 * 50} IPs")
# 准备下一个IP
current += 1
print("IP range ping completed.")
二、多线程处理方式
#多线程
import subprocess
import threading
# 设置IP范围和输出文件路径
start_ip = "66.16.12.1"
end_ip = "66.16.254.254"
output_file = "ping_results.txt"
with open(output_file, 'w', encoding='utf-8') as f:
f.write("# IP Range: 66.16.19.1 to 66.16.254.254\n")
# 辅助函数,将IP地址转换为整数
def ip_to_int(ip):
return sum(int(part) << (24 - 8 * i) for i, part in enumerate(ip.split(".")))
# 辅助函数,将整数转换为IP地址
def int_to_ip(num):
return '.'.join(str((num >> (24 - 8 * i)) & 0xFF) for i in range(4))
# 写入文件的函数
def write_to_file(ip):
with open(output_file, 'a') as f:
f.write(f"{ip}\n")
# 线程工作函数
def ping_ip(ip):
pass
try:
# 尝试ping IP
response = subprocess.run(["ping", "-n", "1", ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if response.returncode == 0:
# Ping成功,调用write_to_file函数写入文件
write_to_file(ip)
print(ip, '成功')
else:
print(ip, '失败')
except Exception as e:
print(f"Error pinging {ip}: {e}")
# 计算IP地址范围
start_int = ip_to_int(start_ip)
end_int = ip_to_int(end_ip)
# 创建线程安全的队列
from queue import Queue
ip_queue = Queue()
# 填充IP队列
for ip_int in range(start_int, end_int + 1):
ip = int_to_ip(ip_int)
ip_queue.put(ip)
# 定义线程数量
num_threads = 10
# 线程工作函数,从队列中获取IP并执行ping操作
def worker(ip_queue):
while not ip_queue.empty():
ip = ip_queue.get()
ping_ip(ip)
ip_queue.task_done()
# 创建并启动线程
threads = []
for _ in range(num_threads):
thread = threading.Thread(target=worker, args=(ip_queue,))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print("IP range ping completed.")
三、将ping成功的IP结果集,进行汇总统计
# 处理ping_results.txt,使之便于查看
from collections import defaultdict
# 辅助函数,用于确定IP的网段
def get_subnet(ip):
return '.'.join(ip.split('.')[:3])
# ping_results.txt文件名
input_file = 'ping_results.txt'
ping_count = 'ping_count.txt'
def sumip(input_file, outputfile=None):
if outputfile:
with open(ping_count, 'w', encoding='utf-8') as f:
f.write("#每个网段可ping通个数:网段,可ping通数量\n")
# 用于存储每个网段IP数量的字典
subnet_count = defaultdict(int)
# 读取文件并统计每个网段的IP数量
with open(input_file, 'r') as file:
# 跳过文件开头的注释行
next(file)
for line in file:
ip = line.strip()
if ip: # 确保跳过空行
subnet = get_subnet(ip)
subnet_count[subnet] += 1
# 打印每个网段及其IP数量
for subnet, count in subnet_count.items():
print(f"网段 {subnet} 有: {count} 个可通IP")
if outputfile:
with open(ping_count, 'a', encoding='utf-8') as f:
f.write(f"{subnet}, {count}\n")
if __name__ == "__main__":
sumip(input_file, outputfile=True)
四、结论
(1)通过直接运行单线程或者多线程代码,会得到一个结果集ping_results.txt。这里记录了所有ping通的IP
(2)用步骤三,对ping_results.txt 中的IP段进行统计。得到文件ping_count.txt。即可得知每一个小IP段有多少台电脑处于联网状态