Python Scapy在使用多个线程时无法嗅探数据包

Python Scapy在使用多个线程时无法嗅探数据包,python,packet-capture,scapy,Python,Packet Capture,Scapy,我将试着用一个简化的例子来说明我的问题 以下是一个非常简单的(单线程)数据包嗅探器(ICMP): 这个嗅探器工作正常,我得到了输出: WARNING: No route found for IPv6 destination :: (no default route?) Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 ec

我将试着用一个简化的例子来说明我的问题

以下是一个非常简单的(单线程)数据包嗅探器(ICMP):

这个嗅探器工作正常,我得到了输出:

WARNING: No route found for IPv6 destination :: (no default route?)
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw
...
接下来,我创建一个用于嗅探数据包的单独线程,并使用队列在嗅探线程和主线程之间传递捕获的数据包:

from threading import Thread
from Queue import Queue, Empty
from scapy.all import *

m_iface = "wlan0"
m_finished = False
m_dst = "192.168.0.1"

def print_summary(pkt):
  print pkt.summary()

def threaded_sniff_target(q):
  global m_finished
  sniff(iface = m_iface, count = 10, filter = "icmp and src {0}".format(m_dst), prn = lambda x : q.put(x))
  m_finished = True

def threaded_sniff():
  q = Queue()
  sniffer = Thread(target = threaded_sniff_target, args = (q,))
  sniffer.daemon = True
  sniffer.start()
  while (not m_finished):
    try:
      pkt = q.get(timeout = 1)
      print_summary(pkt)
    except Empty:
      pass
这个嗅探器也工作得很好,我得到了与上面相同的输出。但是,当我稍微修改主线程时,它会在从数据包队列读取数据之间使用
send()
函数,如下所示:

def threaded_sniff_with_send():
  q = Queue()
  sniffer = Thread(target = threaded_sniff_target, args = (q,))
  sniffer.daemon = True
  sniffer.start()
  while (not m_finished):
    send(IP(dst = m_dst) / ICMP()) # Here
    try:
      pkt = q.get(timeout = 1)
      print_summary(pkt)
    except Empty:
      pass
Python: 2.7.3
Scapy: 2.2.0
OS: Fedora 18
然后我得到以下奇怪的输出(过滤器似乎不工作):

三个嗅探器的脚本可以从下载

我当前的系统配置如下:

def threaded_sniff_with_send():
  q = Queue()
  sniffer = Thread(target = threaded_sniff_target, args = (q,))
  sniffer.daemon = True
  sniffer.start()
  while (not m_finished):
    send(IP(dst = m_dst) / ICMP()) # Here
    try:
      pkt = q.get(timeout = 1)
      print_summary(pkt)
    except Empty:
      pass
Python: 2.7.3
Scapy: 2.2.0
OS: Fedora 18
有趣的是,这三个嗅探器在我的旧电脑上都可以正常工作:

Python: 2.6.4
Scapy: 2.0.0.10 (beta)
OS: Fedora 13
首先,我认为可能是Scapy/Python版本。但即使我在新电脑上安装了完全相同的版本,这种行为依然存在


我不完全确定这是否是一个适合SO的问题(可能是给Scapy的错误报告?)。在这种情况下请原谅。

造成这种情况的主要原因很可能是因为资源锁。Scapy的
sniff()
函数可能必须锁定低级网络资源才能嗅探数据包

延迟两个线程(在启动嗅探器线程之后),您将确保Scapy获得执行此操作所需的时间

要了解我们是如何得出这一结论的,请参见上文评论部分的讨论。
Gl Asiri Rathnayake:)

看起来像一个已知的bug:@ChathurangaChandrasekara:我面临的问题与多线程有关。代码在没有线程的情况下运行良好。@AsiriRathnayake这与网络接口最终处于“预混合模式”以及只有一个源可以绑定到该接口这一事实无关?如果没有,您是否尝试过使用python
threading
库而不是队列?我不完全确定队列系统是如何工作的,但使用
线程
你至少可以更好地控制它的工作,你还可以稍作修改。@AsiriRathnayake我猜如果你在使用
线程
时在执行第二个线程之前放置
睡眠(30)
,它会工作吗?@torx:i放置
时间。睡眠(1)
在启动嗅探器线程之后(因此,稍微延迟了主线程),它就工作了!!!我猜想Scapy的
sniff()
send()
函数之间存在资源重叠,这不是线程安全的,当我们延迟主线程时,这个问题就消失了。请把这一切清楚地表达成一个答案,我会给你分数。干杯谢谢你调查这件事。这也解决了我原来的问题(这是一个更复杂的通信场景)。Scapy的内部可能存在线程安全问题,希望Scapy的人会看到这篇文章:)Yw。如果我有时间,我会给邮件列表发送一条信息,希望有人会注意到这一点:)