簡體   English   中英

Python,使用Queue進行多線程

[英]Python , multithreading with Queue

假設我有2個類Client和Server

class Client(Thread):

    def __init__(self, serv):
        Thread.__init__(self)
        self.serv = serv

    def run(self):
        self.serv.in.put("Hi")

class Server(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.in = Queue()
        self.out = Queue()


    def run(self):
        while True:
            if self.in.get():
                #smth to do

所以。 我正在創建服務器和客戶端,此后,客戶端將隊列中的啟動消息發送到服務器,然后我可以將某些內容發回。

但是,當有2個或3個客戶端連接到1個服務器並使用一個隊列時,可能會出現一些問題。 例如-服務器從客戶端2讀取信息,並認為它是來自客戶端3的啟動消息,依此類推。

因此,我想為每個客戶端創建帶有in Queueout Queue新線程,並在第一條消息之后將其發送回去。 因此,現在,他們將通過這個新線程與服務器進行通信。

我應該使用in隊列和out隊列創建新類並將其發送回客戶端嗎?

我從來沒有使用過線程,所以我只是不知道該怎么做。 我試圖用Google搜索它,但是只找到有關創建線程的教程。

如果您想要的是一台與每個客戶端分別通信的服務器,則可以使用服務器實例中的一個控制隊列來接收初始化消息,然后在每個客戶端中具有通過初始化消息發送到服務器的入隊列和出隊列。

至於誤認消息的風險,我建議使用每種消息類型的類定義,具有明確定義的消息結構。

可能與此類似:

class Message(object):
    pass

class InitMessage(Message):
    def __init__(self, queue_in, queue_out):
        self.queue_in = queue_in
        self.queue_out = queue_out

class Client(Thread):

    def __init__(self, server_queue, name):
        Thread.__init__(self)
        self.control = server_queue
        self.my_in_queue = Queue()
        self.my_out_queue = Queue()
        self.name = name

    def run(self):
        self.control.put(InitMessage(self.my_in_queue, self.my_out_queue))
        while True:
            if not self.my_in_queue.empty():
                message = self.my_in_queue.get()
                print("Client {name} got message from server of type {type}".format(
                    name=self.name, type=type(message).__name__
                ))
                self.my_in_queue.task_done()
                self.my_out_queue.put(Message())

class Server(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.control = Queue()
        self.clients = {}
        self.id = 0

    def run(self):
        while True:
            while not self.control.empty():
                message = self.control.get()
                if isinstance(message, InitMessage):
                    self.clients[self.id] = {'to_client': message.queue_in,
                                             'from_client': message.queue_out}
                    message.queue_in.put(Message())
                    self.id += 1
                self.control.task_done()

            for client in self.clients:
                if not self.clients[client]['from_client'].empty():
                    message = self.clients[client]['from_client'].get()
                    print("got message from client {id}".format(id=client))
                    self.clients[client]['from_client'].task_done()
                    self.clients[client]['to_client'].put(Message())

            sleep(1)

server = Server()
client1 = Client(server.control, "a")
client2 = Client(server.control, "b")
server.start()
client1.start()
client2.start()
server.join()

您必須考慮什么要求,什么對象,交換什么消息以及觸發它們的原因。

據我了解,您有一個服務器線程,它等待來自客戶端的消息,然后將一些東西發送回該客戶端。 這意味着服務器必須標識其客戶端才能向該客戶端發送正確的消息。

我的建議是為服務器使用一個隊列,為每個客戶端使用一個隊列。 當客戶端向服務器發送消息時,它還會將引用傳遞到應將答案回發到該隊列的隊列。

以下是對初始代碼的最小更改,以實現該目標:

從隊列導入從線程導入隊列

class Client(Thread):

    def __init__(self, serv):
        Thread.__init__(self)
        self.serv = serv
        self.inq = Queue()   # declares a queue for the client

    def run(self):
        self.serv.inq.put(("Hi", self.inq))  # send a message, and pass along a response address
        resp = self.inq.get()    # get the response
        print("Got: ", resp)


class Server(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.inq = Queue()  # declare a queue for the server

    def run(self):
        while True:
            req = self.inq.get()   # get a message from input queue
            if not req:
                break
            msg, clientq = req    # parse the message
            # other processing
            clientq.put("From serv: " + msg)  #send back a response

這樣, Server可以為任何數量的不同客戶端提供服務。 但是由於服務器本身不是多線程的,因此您一次只能回答一個客戶端請求。

暫無
暫無

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

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