Python: 线程化ARP ping的奇怪输出
谢谢你花时间来看这个!
我遇到的问题是关于我这个多线程的ARP脚本输出的内容。我想要实现的是把每个活着的主机的IP地址、MAC地址和网络接口卡的厂商信息输出到命令提示符上。
我有一个旧的ARP脚本,没有使用多线程,运行大约需要90秒,输出的内容正是我想要的。
下面是我基于之前那个脚本写的新脚本,加入了多线程。不幸的是,我不知道为什么输出中没有任何值。如果有人能帮我,我将非常感激!
提前谢谢你!
def arp2(ip):
# An ARP scanner for the network.
ips = []
global ans, unans
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip), timeout=2, verbose=0)
for snd, rcv in ans:
#Assign MAC address and IP address to variables mac and ipaddr
mac = rcv.sprintf(r"%Ether.src%")
ipaddr = rcv.sprintf(r"%ARP.psrc%")
#Get NIC vendor code from MAC address
niccode = mac[:8]
niccode = niccode.upper()
print ips
ips.append("end")
#ARPips file amendments
with open( 'C:\Python26\ARPips.prn', 'w+') as f:
f.write("\n".join(map(lambda x: str(x), ips)) + "\n")
#String lookup for NIC vendors. DO NOT CHANGE 'r' TO ANY OTHER VALUE.
with open('C:\Users\TomVB\Desktop\OID2.prn', 'r') as file:
for line in file:
if niccode in file:
return mac, ipaddr, line[8:]
def main():
print "Discovering..."
print ""
print "MAC Address \t \t IP Address \t NIC Vendor"
pool = Pool(processes=12)
Subnetlist = []
for i in range(255):
Subnetlist.append(str(IPInt+str(i)))
global ARPresults
ARPresults = pool.map(arp2, Subnetlist)
pool.close()
pool.join()
print "\n".join(ARPresults)
if __name__ == '__main__':
main()
这个脚本给我的输出是:
Mac Address IP address NIC Vendor
[][]
[]
[]
[]
[]
[][]
[]
[]
然后大约有200行这样的内容。
1 个回答
首先,看起来你在使用多进程,而不是线程。这两者的工作方式是完全不同的,我建议你了解一下这点。不过,针对你现在遇到的问题,原因在别的地方。
arp2
方法是并行执行的。我在这个方法里看到两个问题:
print "%s \t %s \t %s" % (mac, ipaddr, line[8:])
这个语句是输出到标准输出的。在我们的代码中,可能会有多达12个进程同时执行这个语句。Python并不能保证print
语句是原子操作,也就是说,可能会出现一个进程写了一半的内容,另一个进程接着写,这样就会导致输出结果混乱。
同样的情况也适用于
with open( 'C:\Python26\ARPips.prn', 'w+') as f:
f.write("\n".join(map(lambda x: str(x), ips)) + "\n")
这里也没有保证进程之间不会互相干扰,文件内容可能会被搞乱。
最简单的解决办法是在arp2
方法中不要进行任何文件或控制台的输出。可以改为返回结果。pool.map
会安全地收集这些结果,工作方式和普通的map
函数一样。然后你可以再把结果输出到文件或控制台。
如果你想在扫描进行时看到输出,就需要同步这些进程(比如使用multiprocessing.Lock
),确保同一时间只有一个进程在写入或打印。
另外:
在使用Windows风格路径的字符串前加个'r':
x = r'C:\Users\TomVB\Desktop\OID2.prn'
。因为在Python中反斜杠是用来转义的。把
C:\Users\TomVB\Desktop\OID2.prn
的内容加载到一个dict
中,这样会快很多。map(lambda x: str(x), ips)
和map(str, ips)
是等价的。