简体   繁体   English

Python Queue.Queue 在线程 TCP 流处理程序中不起作用

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

i'm trying to make a threaded tcp stream handler class thread and the main thread talk, however Queue.Queue is not doing what i need it too, the server receives data from another program, and i just want to pass it into the main thread for processing here is the code i have so far:我正在尝试创建一个线程化的 tcp 流处理程序类线程和主线程交谈,但是 Queue.Queue 也没有做我需要的事情,服务器从另一个程序接收数据,我只想将它传递到主线程这里处理的线程是我到目前为止的代码:

EDIT: Updated using proposed answer, queue still does nothing i cant even get any print commands to work after i does the self.queue.put(info) its like the whole thing dies.编辑:使用建议的答案更新,队列仍然什么都不做,我什至无法在我执行 self.queue.put(info) 之后让任何打印命令工作,就像整个事情都死了一样。 However it doesn't give me any errors, but the stream handler/thread the data comes in on dies after i put the info into the queue.但是它没有给我任何错误,但是在我将信息放入队列后,数据进入的流处理程序/线程死亡。

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)

And in a main thread class i have:在主线程类中,我有:

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)

However nothing is printing out and it wont pass the data, i know i'm doing something wrong, i just dont know what it is.但是没有打印出来,它不会传递数据,我知道我做错了什么,我只是不知道它是什么。 If anyone has any insight that could help i would greatly appreciate it, thank you.如果有人有任何可以帮助的见解,我将不胜感激,谢谢。

Both the stream handler and the main thread need to be using the same Queue object for this to work.流处理程序和主线程都需要使用相同的Queue对象才能工作。 You're creating separate queue objects in each place.您正在每个地方创建单独的队列对象。 Either use queue as a global variable, if both the client and server code are in the same file, or do this:如果客户端和服务器代码在同一个文件中,或者使用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)

Found I had to adapt a couple of things from the accepted answer.发现我必须从接受的答案中调整一些东西。 This example works (at least in python2.7).这个例子有效(至少在 python2.7 中)。

After starting the server you can test by repeatedly sending with netcat or similar:启动服务器后,您可以通过使用 netcat 或类似工具重复发送来进行测试:

echo "nrtest" | nc -4 127.0.0.1 50514

One can also send with the logger command on linux, but then the handler must look for other strings (this example checks that line starts with "nr", as pr OPs request).也可以在 linux 上使用logger命令发送,但是处理程序必须查找其他字符串(此示例检查该行以“nr”开头,作为 pr OP 请求)。

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

The result is as follows - broken into sections for readability.结果如下 - 为可读性分成几个部分。

Imports:进口:

"""
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

Adding queue to TCPServer:向 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)

Add queue to StreamRequestHandler, tell "handle" what to do, and let "finish" just pass.将队列添加到 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

Define globals and start.定义全局变量并开始。

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

Now start sending something with nc or a similar tool.现在开始使用nc或类似工具发送一些东西。

To end the program, press <ctrl>+C .要结束程序,请按<ctrl>+C

KeyboardInterrupt will "work" if you send a packet.如果您发送数据包, KeyboardInterrupt将“工作”。

  1. Press +C按+C
  2. Send an extra packet发送额外的数据包
  3. Voila, program finishes瞧,程序结束

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM