Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在多线程Python程序中捕获数据包的有效方法_Python_Multithreading_Sockets - Fatal编程技术网

在多线程Python程序中捕获数据包的有效方法

在多线程Python程序中捕获数据包的有效方法,python,multithreading,sockets,Python,Multithreading,Sockets,我正在使用Python实现一个嗅探器。 我需要在所有的数据包细节(VLAN等),所以我使用原始套接字。 在我所有的以太网接口上都有几个嗅探器充当恶魔,所以每个嗅探器都在不同的线程中 除了向其中添加数据包的全局变量(如下面的代码所示),还有什么更好的方法可以在主线程中获得结果 我尝试了排队,但除了增加复杂性之外,没有看到任何特别的好处 import socket, threading def ReceivePackets(): soc = socket.socket(socket.AF_

我正在使用Python实现一个嗅探器。 我需要在所有的数据包细节(VLAN等),所以我使用原始套接字。 在我所有的以太网接口上都有几个嗅探器充当恶魔,所以每个嗅探器都在不同的线程中

除了向其中添加数据包的全局变量(如下面的代码所示),还有什么更好的方法可以在主线程中获得结果

我尝试了排队,但除了增加复杂性之外,没有看到任何特别的好处

import socket, threading

def ReceivePackets():
    soc = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))  
    while 1:
        packet = soc.recv(2000)  
        buffer.append(packet)

def ReadSniffer():
    result = list(buffer) 
    #Clear buffer to start sniffing from scratch after reading
    del buffer[:]
return result
我在程序开始时启动所有以太网接口上的嗅探器,并在需要数据时读取相应的全局缓冲区

buffer = []
t = threading.Thread(target = ReceivePackets)
t.daemon = True
t.start()
...
packets = ReadSniffer()

对于套接字,我总是得到不一致的结果,因为我有不同大小的数据包。套接字可能会捕获我发送几次的所有数据包,但最终会丢失一些数据包

我转到
pcapy
接口,转到
libcap
库,而不是原始套接字,它工作得非常完美和可靠

我将嗅探器类实现为
threading.Thread
的一个子类,因此它在一个单独的线程中启动。实现如下:

class Sniffer(threading.Thread):

    def __init__(self, port):      
        ...
        threading.Thread.__init__(self)
        #Packets will be stored here
        self.result = []
        #Not worry about closing the sniffer thread
        self.daemon = True    

    #Invoked when I start my thread
    def run(self):      
        max_bytes = 16000
        #Important to capture broken packets as I need them
        promiscuous = True
        read_timeout = 100
        pc = pcapy.open_live(str(self.port), max_bytes, promiscuous, read_timeout)
        pc.loop(-1, self.recv_pkts)

    #Do when the packet arrives
    def recv_pkts(self, hdr, packet):
        packetHex = binascii.hexlify(packet)
        self.result.append(packetHex)
        return self.result
要与主程序并行启动嗅探器线程,请执行以下操作:

 sniffer1 = Sniffer(eth1)
 #Start separate thread
 sniffer1.start()

最佳的数据结构不仅取决于如何收集数据包,还取决于如何使用数据包。那么,你如何消费它们呢?还要注意的是,从多个线程添加到列表不是线程安全的。**更新:*我检查了它们,实际上它们是线程安全的,但是最好的做法仍然是使用队列。1)我构造原始数据包(ARP、DHCP、PPPoE),通过以太网L2+交换机发送它们,该交换机根据其配置修改它们。然后我捕获数据包并验证它们是否符合我的预期。我正在运行数据包的类层次结构,所以我基本上比较了两个原始十六进制数据包——一个是从接口接收的,另一个是在我的程序中“虚拟”构造的。2)我有几个全局缓冲区,每个嗅探器/线程一个。它对我来说只是有点难看。但是我验证了它在具有4个端口(4个嗅探器)和相当不错的负载的NIC上工作。好的,您有多少数据包消费者?他们是否需要以某种顺序获取数据包,或者他们只是以FIFO的身份处理数据包?目前,我只有一个消费者——我的主线程。我知道应该在每个接口上获得哪些数据包,因为我也使用主线程启动传输。我尝试测试交换机,并需要在多个接口中验证所有选项,包括复制数据包的选项(如IGMP),工作正常。如果您不需要区分来自不同接口的数据包,我将使用单个队列(即使您这样做,您也可以将该信息与每个数据包一起放入队列)。建模比较容易。然后,您将得到多个生产者和单个消费者的模式。