在多线程Python程序中捕获数据包的有效方法
我正在使用Python实现一个嗅探器。 我需要在所有的数据包细节(VLAN等),所以我使用原始套接字。 在我所有的以太网接口上都有几个嗅探器充当恶魔,所以每个嗅探器都在不同的线程中 除了向其中添加数据包的全局变量(如下面的代码所示),还有什么更好的方法可以在主线程中获得结果 我尝试了排队,但除了增加复杂性之外,没有看到任何特别的好处在多线程Python程序中捕获数据包的有效方法,python,multithreading,sockets,Python,Multithreading,Sockets,我正在使用Python实现一个嗅探器。 我需要在所有的数据包细节(VLAN等),所以我使用原始套接字。 在我所有的以太网接口上都有几个嗅探器充当恶魔,所以每个嗅探器都在不同的线程中 除了向其中添加数据包的全局变量(如下面的代码所示),还有什么更好的方法可以在主线程中获得结果 我尝试了排队,但除了增加复杂性之外,没有看到任何特别的好处 import socket, threading def ReceivePackets(): soc = socket.socket(socket.AF_
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),工作正常。如果您不需要区分来自不同接口的数据包,我将使用单个队列(即使您这样做,您也可以将该信息与每个数据包一起放入队列)。建模比较容易。然后,您将得到多个生产者和单个消费者的模式。