我一直在使用python编写数据包捕获/解析器实用程序。它工作正常,但我的内存泄漏非常严重。当我使用性能分析器时,它总是会归结到我的cap.next()行,这是内存的累积位置。我已经尝试过可以找到的每个实时网络流模块(pypcap,pcapy,scapy,pyshark),但它们似乎都无法改善泄漏。但是,直接使用套接字不仅以显着较小的占用空间开始,而且似乎以可以使用的名义速率增长。
但是,套接字的问题是我错过了很多数据包。我可以告诉我,因为我正在捕获的udp数据包在有效负载的前几个字节中有一个序列号,我用struct将其解包。我有一个tcpdump并排运行,并且tcpdump没有丢失任何数据包。
我猜想我丢失这么多数据包的原因是因为接收缓冲区的套接字很小。我将其增加到我的操作系统允许的最大数量,通过实验,该数量似乎为425984字节。它似乎并没有改变。我的计划是尽快删除消息,然后将它们放入队列,以便我有更多的呼吸空间来处理数据包。到目前为止,我还没有成功。我首先实现了一个队列,然后切换到了heapq,但是没有任何改善。
这是我使用套接字和堆队列的代码的接收部分。通过调试,我几乎可以确定丢失的数据包永远不会进入堆中。
#list for heap queue
uq []
#last sequence number for gap check
lastSeq = 0
#create raw socket
s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))
#check default buffer size
bufsize = s.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
print ("Buffer size [Before]:%d" %bufsize)
#increase the buffer
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF,450560)
#check that buffer has been increased
bufsize = s.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
print ("Buffer size [After]:%d" %bufsize)
#narrow scope to specific interface in effort to cut down on throughput
iface_name = "em1'
s.bind((iface_name,0))
def parse():
eth_length = 14
#wait 2 seconds for queue to fill
time.sleep(2)
while True:
netq = heappop(uq)
packet = netq[0]
ancdata = netq[1]
eth_length = 14
eth_header = packet[:eth_length]
eth = struct.unpack('!6s6sH' , eth_header)
eth_protocol = socket.ntohs(eth[2])
if eth_protocol == 8:
ip_header = packet[eth_length:20+eth_length]
iph = struct.unpack('!BBHHHBBH4s4s' , ip_header)
protocol = iph[6]
if protocol == 17:
try:
MsgSeqNum = struct.unpack_from("<i", udp.body, offset=0)[0]
if (src in lastSeq) and (seqnum != lastSeq[src] + 1):
print('[udpparser] gap detected within parser! last/now',lastSeq[src],seqnum)
lastSeq[src] = seqnum
else:
# print('[udpparser] for good measure, no gap last/now',lastSeq[src],seqnum)
lastSeq[src] = seqnum
netthread = threading.Thread(target=parse, )
netthread.daemon = True
netthread.start()
while True:
packet, ancdata, flags, address = s.recvmsg(65545, 1024)
heappush(uq,(packet,ancdata,))