【问题标题】:Python Queue and Threading confusionPython 队列和线程混淆
【发布时间】:2015-07-09 02:25:22
【问题描述】:

我用 Python 做了一个嗅探器,它计算 IP 数据包的大小。我尝试通过两种方式获取尺寸:

1) 只需计算 len(pkt)

2) 通过从 IP 标头中提取数据包长度并为以太网标头添加 14 个字节

将 len(pkt) 的结果与从 IP 标头提取的值进行比较时,它们几乎总是相同的(好吧,对于非常少的数据包,存在 4-6 个字节的差异,但这是另一个问题)。

但是一旦我在我的代码中实现了队列和线程,来自 len(pkt) 的大小和从 IP 标头中提取的值在大多数情况下是完全不同的。有时只有几个字节的差异,有时有几百字节的差异。但很少有相同的。

我实现线程的代码如下。如果我在实现线程/队列的方式上犯了错误,或者我做错了什么,有人知道吗?

import pcap
import struct
import dpkt
from Queue import Queue
from threading import Thread

def packet_handler():
    ts,pkt=q.get()
    eth=dpkt.ethernet.Ethernet(pkt)
    if eth.type != dpkt.ethernet.ETH_TYPE_IP:
        return
    a=struct.unpack('!BBHHHBBH4s4s', pkt[14:34])
    print a[2]+14,len(pkt)

def start():  
    pc.loop(0,lambda ts,pkt: q.put((ts,pkt)))

q=Queue()
pc=pcap.pcap(name="eth0")
start_sniffer=Thread(target=start)
start_sniffer.start()

while True:
    packet_handler()

部分输出如下所示:

419 1454
419 419
54 60
389 60
389 389
405 60
405 405
405 60
405 405
54 60
54 60
493 491
491 492
491 493
491 491
502 502
54 60

【问题讨论】:

  • lambda 的惰性求值是否可能导致问题?更多讨论请见python.org/~jeremy/weblog/040204.html
  • 不,我也试过做一个单独的回调函数。
  • 这可能与问题无关,但是当它可以访问pc 时,为什么要将q 传递给start?两者都是全局变量。
  • 你是对的。我不需要传递这些变量。我将编辑帖子以避免进一步混淆。谢谢!我也用修改后的代码再次测试了一下,问题依旧……
  • 我无法重现该问题。运行您发布的代码会产生正确的结果(即a[2]+14 == len(pkt))。你能复制+粘贴运行它的输出吗?

标签: python multithreading


【解决方案1】:

我想我解决了。我改变了这一行:

pc.loop(0,lambda ts,pkt: q.put((str(ts),str(pkt))))

也就是说,我在将 ts 和 pkt 添加到队列之前将它们转换为字符串。

对于 4-6 个字节,少数数据包的大小仍然不同,但非线程版本也是如此。我可能会在新帖子中询问这个问题。

感谢大家的帮助!!!

【讨论】:

    最近更新 更多