Ruby中提取IP地址范围子集以规避内存溢出问题
嘿,我之前处理大规模IP扫描任务时也碰到过一模一样的内存溢出问题,给你个针对性的解决方案:
解决大IP段内存不足问题:提取32个地址子集
核心问题在于处理10.234.xxx.1/24这类/24段时,直接把整个IP范围转成数组会生成256个元素,当有大量这类段时很容易撑爆内存。我们可以均匀抽取32个IP来替代全量数组,既保持样本代表性,又大幅降低内存占用。
修改后的代码片段
ips.each do |ip| ip_from = if ip.instance_of?(Nexpose::HostName) ip.host else # 处理IP范围:不再全量转换,而是抽取32个样本 ip_range = ip.from..ip.to total_ips = ip_range.size # 如果IP总数<=32,直接取全部;否则按间隔抽取32个 if total_ips <= 32 ip_range.map(&:to_s) else step = total_ips / 32 # 从范围中按步长取元素,确保覆盖整个段 (0..31).map { |i| ip_range.begin + (i * step) }.map(&:to_s) end end # 后续你的处理逻辑:ip_from2 = ip_from.select{ |i|... } end
关键逻辑解释
- 适配小范围场景:先计算当前IP段的总数量,如果本身就小于等于32个,直接保留全量,避免抽样丢失数据。
- 均匀覆盖抽样:当IP总数大于32时,计算步长(总数量/32),从起始IP开始每步长取一个IP,这样能均匀覆盖整个/24段,不会集中在某一小片区域,适合扫描、检测这类需要代表性样本的场景。
- 从根源减少内存占用:直接通过计算偏移量获取目标IP,而不是先把整个范围转成数组,彻底避免全量数组带来的内存开销。
可选优化:随机抽样
如果你的场景需要随机样本,也可以用随机抽取32个唯一IP的方式,代码如下:
else ip_range = ip.from..ip.to total_ips = ip_range.size if total_ips <= 32 ip_range.map(&:to_s) else # 生成32个不重复的随机索引,对应到IP范围 random_indices = (0...total_ips).to_a.sample(32).sort random_indices.map { |idx| ip_range.begin + idx }.map(&:to_s) end end
内容的提问来源于stack exchange,提问作者Derek
相关产品推荐
相关产品推荐

