queue.get() returns 只有一项
queue.get() returns only one item
我正在构建一个小嗅探器来接收网络中设备的应答。我宁愿通过实现 Scapys Packet class 的 answers()
方法来解决这个问题,但这并没有像预期的那样工作。我试图通过首先创建一个嗅探线程来绕过它,然后向设备发送一个数据包并等待答案。
import threading
from scapy.all import sniff
class SnifferThread(threading.Thread):
""" Thread that sniffs for incoming packets
"""
def __init__(self, queue, timeout=1, checkFunction=None, filter=None):
""" Initialization method """
if queue is None:
raise Exception, "queue must not be None"
self.q = queue
self.filter = filter
self.timeout = timeout
self.checkFunction = checkFunction
threading.Thread.__init__(self)
def putInQueue(self, packet):
""" Checks packet and puts it into the queue if it matches """
if self.checkFunction:
if self.checkFunction(packet):
self.q.put(packet)
print "put"
else:
self.q.put(packet)
def run(self):
""" Executes the sniffing """
sniff(
timeout=self.timeout,
filter=self.filter,
prn=lambda pkt: self.putInQueue(pkt)
)
def has_IAm(packet):
""" Checks whether the packet contains an IAm """
if packet.haslayer(APDU):
if (packet[APDU].serviceChoice\
== BACNetAPDUUnconfirmedServiceChoice.I_AM):
print "has I_AM"
return True
def discoverDevices():
""" Sends WhoIs packet and prints answers """
bindBACNetLayers()
myQ = Queue.Queue()
sniffer = SnifferThread(
queue=myQ,
checkFunction=has_IAm,
filter=FILTER_BACNET
)
sniffer.start()
sendp(
getBACNetWhoIsPacket(
"192.168.1.1",
"192.168.1.255"
),
verbose=False
)
while sniffer.isAlive():
print "still alive"
print myQ.qsize()
answers = PacketList()
answers.append(myQ.get())
answers.show()
discoverDevices()
执行它时,我可以在 Wireshark 中看到两个设备通过发送 I_AM 数据包进行响应。我还可以看到队列中有两个项目,因为最后 print myQ.qsize()
打印 2
。所以我希望 myQ.get()
到 return 两个数据包对象,然后在执行 answers.show()
时应该在终端中显示它们,但是不知何故只显示一个数据包 - 第一个被接收的数据包。我使用 myQ.get()
不正确吗?
我就这样解决了
while sniffer.isAlive():
pass
answers = PacketList()
for _ in range(myQ.qsize()):
answers.append(myQ.get())
get
将始终 return 一个项目,正如 documentation 所说:
Remove and return an item from the queue.
您应该重复调用 get
,直到队列为空。
我正在构建一个小嗅探器来接收网络中设备的应答。我宁愿通过实现 Scapys Packet class 的 answers()
方法来解决这个问题,但这并没有像预期的那样工作。我试图通过首先创建一个嗅探线程来绕过它,然后向设备发送一个数据包并等待答案。
import threading
from scapy.all import sniff
class SnifferThread(threading.Thread):
""" Thread that sniffs for incoming packets
"""
def __init__(self, queue, timeout=1, checkFunction=None, filter=None):
""" Initialization method """
if queue is None:
raise Exception, "queue must not be None"
self.q = queue
self.filter = filter
self.timeout = timeout
self.checkFunction = checkFunction
threading.Thread.__init__(self)
def putInQueue(self, packet):
""" Checks packet and puts it into the queue if it matches """
if self.checkFunction:
if self.checkFunction(packet):
self.q.put(packet)
print "put"
else:
self.q.put(packet)
def run(self):
""" Executes the sniffing """
sniff(
timeout=self.timeout,
filter=self.filter,
prn=lambda pkt: self.putInQueue(pkt)
)
def has_IAm(packet):
""" Checks whether the packet contains an IAm """
if packet.haslayer(APDU):
if (packet[APDU].serviceChoice\
== BACNetAPDUUnconfirmedServiceChoice.I_AM):
print "has I_AM"
return True
def discoverDevices():
""" Sends WhoIs packet and prints answers """
bindBACNetLayers()
myQ = Queue.Queue()
sniffer = SnifferThread(
queue=myQ,
checkFunction=has_IAm,
filter=FILTER_BACNET
)
sniffer.start()
sendp(
getBACNetWhoIsPacket(
"192.168.1.1",
"192.168.1.255"
),
verbose=False
)
while sniffer.isAlive():
print "still alive"
print myQ.qsize()
answers = PacketList()
answers.append(myQ.get())
answers.show()
discoverDevices()
执行它时,我可以在 Wireshark 中看到两个设备通过发送 I_AM 数据包进行响应。我还可以看到队列中有两个项目,因为最后 print myQ.qsize()
打印 2
。所以我希望 myQ.get()
到 return 两个数据包对象,然后在执行 answers.show()
时应该在终端中显示它们,但是不知何故只显示一个数据包 - 第一个被接收的数据包。我使用 myQ.get()
不正确吗?
我就这样解决了
while sniffer.isAlive():
pass
answers = PacketList()
for _ in range(myQ.qsize()):
answers.append(myQ.get())
get
将始终 return 一个项目,正如 documentation 所说:
Remove and return an item from the queue.
您应该重复调用 get
,直到队列为空。