简体   繁体   English

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

[英]Efficient way to capture packets in multithreading Python program

I'm implementing a sniffer using Python. 我正在使用Python实现嗅探器。 I need in all packet details (VLAN etc.) so I'm using RAW sockets. 我需要所有数据包详细信息(VLAN等),所以我使用的是RAW套接字。 There are several sniffers working as demons on all of my Ethernet interfaces, so each one is in a different thread. 我所有的以太网接口上都有多个嗅探器充当恶魔,因此每个嗅探器都位于不同的线程中。

Is there any better way to get the results in my main thread besides global variable to which I add my packets (as in the code below)? 除了将数据包添加到的全局变量之外,还有什么更好的方法可以在主线程中获得结果(如下面的代码所示)?

I tried Queue but didn't see any particular benefits besides added complexity. 我尝试了Queue,但是除了增加复杂性之外,没有看到任何其他好处。

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

I start sniffers on all of my Ethernet interfaces at the beginning of the program and read the corresponding global buffers when I need the data. 我在程序开始时在所有以太网接口上启动嗅探器,并在需要数据时读取相应的全局缓冲区。

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

With sockets I always got inconsistent results, since I have various packets with different packet size. 使用套接字时,总是得到不一致的结果,因为我有各种不同大小的数据包。 A socket may capture all the packets I send few times, but eventually it loses some packets. 一个套接字可以捕获我几次发送的所有数据包,但最终会丢失一些数据包。

I moved to pcapy interface to libcap library instead of raw sockets and it works perfectly and very reliably. 我移到了libcap库的pcapy接口,而不是原始套接字,它可以完美且非常可靠地工作。

I implemented Sniffer class as a subclass of threading.Thread so it starts in a separate thread. 我将Sniffer类实现为threading.Thread的子类,因此它在单独的线程中启动。 The implementation is like this: 实现是这样的:

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

To start sniffer thread in parallel to your main program: 要与主程序并行启动嗅探器线程:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM