Python脚本停留在queue.join()

时间:2016-11-06 22:01:26

标签: python multithreading python-3.x

我正在尝试实现一个服务器来处理许多客户端(来自thenewboston python反向shell教程)。我有完全相同的代码但是当我运行脚本时它会卡在queue.join()。如何使它工作?我无法弄清楚。

这是代码

import socket
import sys
import threading
from queue import Queue

NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue()
all_connections = []
all_addresses = []

# thread 1

# create socket (allows two computers to connect)

def socket_create():
    try:
        global host # ip address of the server
        global port # port is to identify the kind of data
        global s
        host = ''
        port = 9999
        s = socket.socket()
    except socket.error as msg:
        print("Socket creation error: " + str(msg))
    return

# bind socket to port and wait for connection from client

def socket_bind():
    try:
        global host
        global port
        global s
        print("Binding socket to port: " + str(port))
        s.bind((host, port))
        s.listen(5)
        # 5 is the no. of conections that can be made before server starts     rejecting other requests  
    except socket.error as msg:
        print("Socket binding error: " + str(msg) + "\n" + "Retrying...")
        socket_bind()
    return

# accept connections from multiple clients and save to list

def accept_connections():
    for c in all_connections:
        c.close()
    del all_connections[:]
    del all_addresses[:]
    while 1:
        try:
            conn, address = s.accept()
            conn.setblocking(1)
            all_connections.append(conn)
            all_addresses.append(address)
            print("\nConnection has been establish: " + address[0])
        except:
            print("Error accepting connections")
    return

# thread 2

# custom command promt for sending commands remotely

def start_turtle():
    while True:
        cmd = input('turtle> ')
        if cmd == 'list':
            list_connections()
        elif 'select' in cmd:
            conn = get_target(cmd)
            if conn is not None:
                send_target_commands(conn)
        else:
            print("Command not recognized")
    return

# listing all the connections with indexing in the custom promt

def list_connections():
    results = ''
    for i, conn in enumerate(all_connections):
        try:
            conn.send(str.encode(' '))
            conn.recv(20480)
        except:
            del all_connections[i]
            del all_addresses[i]
            continue
        results += str(i) + '   ' + str(all_addresses[i][0]) + '   ' +      str(all_addresses[i][1]) + '\n'

    print('-----Clients-----' + '\n' + results)
    return

# select a target client

def get_target(cmd):
    try:
        target = cmd.replace('select ', '')
        target = int(target)
        conn = all_connections[target]
        print("You are now connected to " + str(all_addresses[target][0]))
        print(str(all_addresses[target][0]) + '> ', end="")
        return conn
    except:
        print("Not a valid selection")
        return None
    return

# connect with remote target client

def send_target_commands(conn):
    while True:
        try:
            cmd = input()
            if len(str.encode(cmd)) > 0:
                conn.send(str.encode(cmd))
                client_response = str(conn.recv(20480), "utf-8")
                print(client_response, end="")
            if cmd == "quit":
                break
        except:
            print("Connection was lost")
            break
    return

# create worker threads

def create_workers():
    for _ in range(NUMBER_OF_THREADS):
        t = threading.Thread(target=work)
        t.daemon = True
        t.start
    return

# do the next job in the queue (one handles connections, other sends commands)

def work():
    while True:
        x = queue.get()
        if x == 1:
            socket_create()
            socket_bind()
            accept_connections()
        if x == 2:
            start_turtle()
        queue.task_done()
    return

# create jobs for later extracting them and assigning them to the threads

def create_jobs():
    for x in JOB_NUMBER:
        queue.put(x)
    queue.join()
    return

def main():  
    create_workers()
    create_jobs()

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:0)

由于您在 start_turtle 处使用无限循环(而True),而在 accept_connections 处使用(而1),因此它们不会返回。 由于他们没有返回功能工作从不调用 queue.task_done(),因此队列卡住了。

我担心您需要执行以下操作之一:

  1. 在并行进程或线程中启动 start_turtle accept_connections
  2. 请确保他们应该调用 queue.task_done()
  3. 例如,您可以将队列包含为参数,并在启动无限循环之前调用它(第二个选项)。

    def work():
        while True:
        x = queue.get()
        if x == 1:
            socket_create()
            socket_bind()
            accept_connections(queue)  # call queue.task_done() there
        if x == 2:
            start_turtle(queue)  # call queue.task_done() in start_turtle
        return
    
    def start_turtle(queue):
        queue.task_done()  # Join one item from the queue
        while True:
            cmd = input('turtle> ')
            if cmd == 'list':
                list_connections()
            elif 'select' in cmd:
                conn = get_target(cmd)
                if conn is not None:
                    send_target_commands(conn)
            else:
                print("Command not recognized")
        return
    

    另一方面,在 create_workers 中,您不会调用线程的start方法,因此您的工作人员并未真正启动。 也许这是一个错字。

    def create_workers():
        for _ in range(NUMBER_OF_THREADS):
            t = threading.Thread(target=work)
            t.daemon = True
            # t.start  # Not starting the Thread
            t.start()  # You need to call the start method
        return