簡體   English   中英

Python Queue.Queue 在線程 TCP 流處理程序中不起作用

[英]Python Queue.Queue wont work in threaded TCP Stream Handler

我正在嘗試創建一個線程化的 tcp 流處理程序類線程和主線程交談,但是 Queue.Queue 也沒有做我需要的事情,服務器從另一個程序接收數據,我只想將它傳遞到主線程這里處理的線程是我到目前為止的代碼:

編輯:使用建議的答案更新,隊列仍然什么都不做,我什至無法在我執行 self.queue.put(info) 之后讓任何打印命令工作,就像整個事情都死了一樣。 但是它沒有給我任何錯誤,但是在我將信息放入隊列后,數據進入的流處理程序/線程死亡。

class ThreadedTCPStreamHandler(SocketServer.StreamRequestHandler):

    def __init__(self, request, client_address, server):
         SocketServer.StreamRequestHandler.__init__(self, request, client_address, server)
         self.queue = self.server.queue

    def handle(self):
                while True:
                    try:
                        self.data = self.rfile.readline().strip()
                        cur_thread = threading.current_thread()
                        command = self.data[0:2]
                        if command == "nr":
                            info = self.data[2:]
                            t1 = info.split("|")
                            title = t1[0]
                            self.queue.put(info)

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):

        def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, queue=None):
            self.queue = queue
            SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=bind_and_activate)

在主線程類中,我有:

q = Queue.Queue()
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPStreamHandler, queue=q)
ip, port = server.server_address

server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
while True:
        try:
            item = q.get()
            print item
            q.task_done()
            q.join()
        except KeyboardInterrupt:
            server.shutdown()
            sys.exit(0)

但是沒有打印出來,它不會傳遞數據,我知道我做錯了什么,我只是不知道它是什么。 如果有人有任何可以幫助的見解,我將不勝感激,謝謝。

流處理程序和主線程都需要使用相同的Queue對象才能工作。 您正在每個地方創建單獨的隊列對象。 如果客戶端和服務器代碼在同一個文件中,或者使用queue作為全局變量,或者執行以下操作:

class ThreadedTCPStreamServer(ThreadingMixin, TCPServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True,
                 queue=None):
        self.queue = queue
        TCPServer.__init__(self, server_address, RequestHandlerClass,
                           bind_and_activate=bind_and_activate)

class ThreadedTCPStreamHandler(SocketServer.StreamRequestHandler):
    def __init__(self, request, client_address, server):
        self.queue = server.queue
        StreamRequestHandler.__init__(self, request, client_address, server)

    def handle(self):
        while True:
            self.data = self.rfile.readline().strip()
            if not self.data:
                break
            cur_thread = threading.current_thread()
            command = self.data[0:2]
            if command == "nr":
                info = self.data[2:]
                t1 = info.split("|")
                title = t1[0]
                self.queue.put(info)
                self.finish()


q = Queue.Queue()
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPStreamHandler, queue=q)
ip, port = server.server_address

server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
while True:
        try:
            item = q.get()
            print item
            q.task_done()
            q.join()
        except KeyboardInterrupt:
            server.shutdown()
            sys.exit(0)

發現我必須從接受的答案中調整一些東西。 這個例子有效(至少在 python2.7 中)。

啟動服務器后,您可以通過使用 netcat 或類似工具重復發送來進行測試:

echo "nrtest" | nc -4 127.0.0.1 50514

也可以在 linux 上使用logger命令發送,但是處理程序必須查找其他字符串(此示例檢查該行以“nr”開頭,作為 pr OP 請求)。

logger -T -n 127.0.0.1 -P 50514 "Test message"

結果如下 - 為可讀性分成幾個部分。

進口:

"""
Based on https://stackoverflow.com/a/25246157/2045924
"""
import threading
import Queue
import sys
import SocketServer
from SocketServer import StreamRequestHandler
from SocketServer import TCPServer
from SocketServer import ThreadingMixIn

向 TCPServer 添加隊列:

class ThreadedTCPStreamServer(ThreadingMixIn, TCPServer):
    """ThreadedTCPStreamServer."""
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True,
                 queue=None):
        self.queue = queue
        TCPServer.__init__(self, server_address, RequestHandlerClass,
                           bind_and_activate=bind_and_activate)

將隊列添加到 StreamRequestHandler,告訴“處理”要做什么,讓“完成”通過。

class ThreadedTCPStreamHandler(SocketServer.StreamRequestHandler):
    """ThreadedTCPStreamHandler."""
    def __init__(self, request, client_address, server):
        self.queue = server.queue
        StreamRequestHandler.__init__(self, request, client_address, server)

    def handle(self):
        while True:
            self.data = self.rfile.readline().strip()
            if not self.data:
                break
            __cur_thread = threading.current_thread()
            self.finish()
            command = self.data[0:2]
            if command == "nr":
                info = self.data[2:]
                __t1 = info.split("|")
                __title = __t1[0]
                self.queue.put(info)
                self.finish()
    def finish(self):
        pass

定義全局變量並開始。

HOST = '127.0.0.1'
PORT = 50514

# QUEUE must be defined _outside_.
QUEUE = Queue.Queue()
QTIMEOUT = 1

# Setup instance of my own ThreadedTCPStreamServer with my own ThreadedTCPStreamHandler.
SERVER = ThreadedTCPStreamServer((HOST, PORT), ThreadedTCPStreamHandler, queue=QUEUE)
__IP, __PORT = SERVER.server_address

# Start the server
SERVER_THREAD = threading.Thread(target=SERVER.serve_forever)
SERVER_THREAD.daemon = True
SERVER_THREAD.start()

while True:
    try:
        #ITEM = QUEUE.get(block=True, timeout=QTIMEOUT)
        ITEM = QUEUE.get()
        print 'qsize({s}): {i}'.format(s=QUEUE.qsize(), i=ITEM)
        QUEUE.task_done()
        QUEUE.join()
    except KeyboardInterrupt:
        SERVER.shutdown()
        sys.exit(0)
    #except Queue.Empty:
    #    print 'Got Queue.Empty after waiting for {t}. Continuing...'.format(t=QTIMEOUT)
    #    continue

現在開始使用nc或類似工具發送一些東西。

要結束程序,請按<ctrl>+C

如果您發送數據包, KeyboardInterrupt將“工作”。

  1. 按+C
  2. 發送額外的數據包
  3. 瞧,程序結束

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM