Python:线程ARP ping的奇怪输出

时间:2014-03-19 18:16:16

标签: python multithreading output arp

感谢您花时间看看这个!

我遇到的问题是我的线程ARP脚本的输出。我想要实现的是将每个活动主机输出的IP地址,MAC地址和NIC供应商输出到命令提示符。

我有一个没有线程的旧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 个答案:

答案 0 :(得分:0)

首先,看起来你正在使用多处理而不是线程。这两个表现完全不同,我建议你研究一下。无论如何,对于手头的问题,原因还在其他地方。

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)