Python 从主代码到多个线程(如果有套接字的话)的通信

Python 从主代码到多个线程(如果有套接字的话)的通信,python,sockets,python-2.7,queue,python-multithreading,Python,Sockets,Python 2.7,Queue,Python Multithreading,我一直在阅读线程、套接字和队列方面的内容,但在这方面的工作原理上,我仍然有一个思维障碍。现在我有一个线程服务器,它接受端口上的连接,然后派生出一个新线程(以及新的、随机分配的系统端口)来处理剩余的工作。我想做的是从主线程开始,与子线程通信,并发送它们要做的工作。以下是我的线程服务器的一个示例: import threading, time, socket class ClientThread(threading.Thread): def __init__(self,ip,port,c

我一直在阅读线程、套接字和队列方面的内容,但在这方面的工作原理上,我仍然有一个思维障碍。现在我有一个线程服务器,它接受端口上的连接,然后派生出一个新线程(以及新的、随机分配的系统端口)来处理剩余的工作。我想做的是从主线程开始,与子线程通信,并发送它们要做的工作。以下是我的线程服务器的一个示例:

import threading, time, socket

class ClientThread(threading.Thread):

    def __init__(self,ip,port,clientsocket):
        threading.Thread.__init__(self)
        self.ip = ip
        self.port = port
        self.csocket = clientsocket
        print ("[+] New thread started for "+ip+":"+str(port))

    def run(self):
        # Stuff happens here
        # keep alive
        while True:
            #send a keepalive to the network device
            data = 'someinfo'
            self.csocket.sendall(data)
            #receive keepalive
            data = self.csocket.recv(56)
            time.sleep(8)

while True:
    host = "127.0.0.1"
    port = 3000
    tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    tcpsock.bind((host,port))   
    tcpsock.listen(5)
    print ("\nListening for incoming connections...")
    (clientsock, (ip, port)) = tcpsock.accept()
    newthread = ClientThread(ip, port, clientsock)
    newthread.start()
因此,我的服务器有一个超级简单的示例,它接受传入的连接并剥离线程以保持连接处于活动状态。我现在想做的是合并队列,允许我将“数据”发送到要发送到网络设备的单个线程,然后从设备获取其响应。通过这种方式,我可以通过各自的线程/套接字与多个设备交互,所有这些都来自我的主代码。我只是需要一点帮助来找出最好的方法

如果它是一个队列,我如何告诉队列与哪个线程对话

提前谢谢你

[编辑1]


举个例子,假设这些设备是打开继电器的简单设备。因此,每个线程都将连接到主线程,生成各自的线程,然后只向keep-alive发送响应。在任何时候,我都想中断保持活动状态,或者只是在之后发送命令,即打开继电器或关闭继电器。设备将执行该命令,然后响应(确认、错误等)。主线程将从子线程接收此响应,然后提示输入新命令,或者在keep-alive运行时等待。因此,我可以坐在终端上打开和关闭继电器。

首先,您需要一个线程来处理用户输入,一个线程来处理传入的设备连接,以及一个线程来处理每个连接的设备

然后,您可以为每个
ClientThread
实例创建一个单独的
队列
,以从用户输入线程接收数据,并维护您创建的所有
队列
实例的dict
dict
将需要键入以某种方式识别设备的内容-在下面的示例中,我使用每个连接的
作为键。因此,现在用户输入线程可以接收来自用户的请求,并将其发送到适当的线程。最后一部分是返回一个响应。您可以在所有线程中重复使用
队列
实例来执行此操作,假设您想在等待设备响应用户输入的请求时进行阻止

下面是一个未经测试的示例,演示了所有这些:

import threading
import socket
import Queue

class ClientThread(threading.Thread):

    def __init__(self,ip,port,clientsocket, in_q, out_q):
        threading.Thread.__init__(self)
        self.ip = ip
        self.port = port
        self.csocket = clientsocket
        self.in_q = in_q
        self.out_q = out_q
        self._tid = "{}:{}".format(ip, port)
        self.daemon = True # Assuming you want the client thread to shutdown when the main thread does
        print ("[+] New thread started for "+ip+":"+str(port))

    def run(self):
        # Stuff happens here
        while True:
            try:
                # Wait 8 seconds for an incoming command
                cmd = self.in_q.get(timeout=8)
                self.csocket.sendall(cmd)
                data = self.csocket.recv(56)
                # Send result to main thread.
                self.out_q.put({'tid' : self._tid, 'data' : data})
            except Queue.Empty:
                # No incoming command after 8 seconds, do a keep-alive instead.
                data = 'someinfo'
                self.csocket.sendall(data)
                data = self.csocket.recv(56)

def handle_socket_connections(resp_queue):
    """ Thread for handling connections from devices. """
    while True:
        host = "127.0.0.1"
        port = 3000
        tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        tcpsock.bind((host,port))   
        tcpsock.listen(5)
        print ("\nListening for incoming connections...")
        (clientsock, (ip, port)) = tcpsock.accept()
        q = Queue.Queue() # Create a Queue for sending commands to this device.
        queues["{}:{}".format(ip,port)] = q
        newthread = ClientThread(ip, port, clientsock, q, resp_queue)
        newthread.start()


queues = {} # dict for managing input queues
resp_queue = Queue.Queue()  # Shared response queue
socket_handler = threading.Thread(target=handle_socket_connections, args=(resp_queue,))
socket_handler.daemon = True
socket_handler.start()

# Wait for user input
while True:
    # example input format: '1.2.3.4:55 ON'
    in_data = raw_input("Enter using the format - <IP>:<Port> <cmd>")
    if in_data == "EXIT":
        break
    ip_port, cmd = in_data.split()
    try:
        queues[ip_port].put(cmd)  # Send command to the appropriate thread.
        result = resp_queue.get()  # Wait for a response.
        print("Got '{data}' from {tid}".format(**result))
    except KeyError:
        print("No conection on {}".format(ip_port))
导入线程
导入套接字
导入队列
类ClientThread(threading.Thread):
定义初始化(self,ip,port,clientsocket,in_q,out_q):
threading.Thread.\uuuuu init\uuuuuu(自)
self.ip=ip
self.port=端口
self.csocket=clientsocket
self.in_q=in_q
self.out\u q=out\u q
self._tid=“{}:{}”。格式(ip,端口)
self.daemon=True#假设希望在主线程关闭时关闭客户端线程
打印(“[+]为“+ip+”:“+str(端口)”启动的新线程)
def运行(自):
#这里发生了很多事情
尽管如此:
尝试:
#等待8秒钟,等待传入命令
cmd=self.in_q.get(超时=8)
self.csocket.sendall(cmd)
数据=self.csocket.recv(56)
#将结果发送到主线程。
self.out_q.put({'tid':self.'tid',data':data})
队列除外。空:
#8秒后没有传入命令,请改为执行保持活动。
数据='someinfo'
self.csocket.sendall(数据)
数据=self.csocket.recv(56)
def句柄\u套接字\u连接(响应队列):
“”“处理来自设备的连接的线程。”“”
尽管如此:
host=“127.0.0.1”
端口=3000
tcpsock=socket.socket(socket.AF\u INET,socket.SOCK\u流)
tcpsock.setsockopt(socket.SOL_socket,socket.SO_REUSEADDR,1)
tcpsock.bind((主机、端口))
tcpsock.听(5)
打印(“\n正在为传入连接进行列表…”)
(clientsock,(ip,端口))=tcpsock.accept()
q=Queue.Queue()#创建一个队列,用于向该设备发送命令。
队列[“{}:{}”.format(ip,端口)]=q
newthread=ClientThread(ip、端口、clientsock、q、resp_队列)
newthread.start()
queues={}用于管理输入队列的dict
resp_queue=queue.queue()#共享响应队列
socket\u handler=threading.Thread(target=handle\u socket\u connections,args=(resp\u queue,))
socket\u handler.daemon=True
socket_handler.start()
#等待用户输入
尽管如此:
#输入格式示例:“1.2.3.4:55开”
in_data=raw_输入(“使用以下格式输入-:”)
如果in_data==“退出”:
打破
ip_端口,cmd=in_data.split()
尝试:
队列[ip_端口].put(cmd)#将命令发送到相应的线程。
result=resp_queue.get()#等待响应。
打印(“从{tid}获取{data}”。格式(**结果))
除KeyError外:
打印(“在{}上没有连接”。格式(ip_端口))

那么您希望您的主线程处理新连接的生成,同时也处理来自网络设备的响应?我想你需要两个线程。另外,您希望如何处理来自网络设备的响应?另外,您如何决定向每个线程发送什么数据,以及何时发送?理想情况下,我希望主线程处理所有事情,但我不介意是否有一个线程生成其他线程,以及一个线程管理网络设备。至于响应,我可能会在屏幕上显示它们(SSH终端),或者将它们存储在列表中,或者保存到文件中。坦白地说,我还没走那么远。我一直在想的是如何