【问题标题】:Return values from thread Python从线程 Python 返回值
【发布时间】:2021-10-24 12:56:54
【问题描述】:

我有一个这样的多客户端服务器设置。这段代码工作正常,但是如果我需要将消息从 handle_client 返回到 main 并在不使用全局变量的情况下存储它们怎么办?

服务器端

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
    print(f"[NEW CONNECTION] {addr} connected.")

    connected = True
    while connected:
        msg_length = conn.recv(HEADER).decode(FORMAT)
        if msg_length:
            msg_length = int(msg_length)
            msg = conn.recv(msg_length).decode(FORMAT)
            if msg == DISCONNECT_MESSAGE:
                connected = False

            print(f"[{addr}] {msg}")
            conn.send("Msg received".encode(FORMAT))

    conn.close()
    

def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    while True:
        conn, addr = server.accept()
        thread = threading.Thread(target=handle_client, args=(conn, addr))
        thread.start()
        print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")

print("[STARTING] server is starting...")
start()

在客户端

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)

def send(msg):
    message = msg.encode(FORMAT)
    msg_length = len(message)
    send_length = str(msg_length).encode(FORMAT)
    send_length += b' ' * (HEADER - len(send_length))
    client.send(send_length)
    client.send(message)
    print(client.recv(2048).decode(FORMAT))

send("Hello World!")
input()
send("Hello Everyone!")

send(DISCONNECT_MESSAGE)

提前感谢您的帮助

【问题讨论】:

  • 当你说“返回主”时,这实际上是什么意思?
  • 假设 3 个客户端将连接,所以我想在列表中返回 3 条消息
  • 但是您的客户端可能在时间上相距很远,所以这是一条消息三遍。 main 将如何处理这些消息?
  • 仅供参考,请考虑 recv(n) 在断开连接时返回 1 到 n 个字节或 0。 recv(n) 保证准确返回 n 字节。在正确的网络条件下,此代码可能会失败。 send() 有类似的问题。至少考虑sendall()
  • @ThodorisSamaras 这可能吗?如果第 4 个客户端连接但为时已晚,因为列表已经“返回到主列表”怎么办?是否应该等待查看第四个客户端是否连接?应该等多久?而且它也没有真正解释“回归主”这几个字。

标签: python multithreading sockets


【解决方案1】:

一种方法是使用线程安全的queuehandle_client 函数将其作为参数,并可以在需要时推送项目。 需要有另一个线程来移除项目,但这可能是主线程。在这种情况下,您将需要另一个线程阻塞server.accept() 等待启动新的handle_client 线程。

【讨论】:

    【解决方案2】:

    也许从一个线程向另一个线程发送数据最安全的方法是使用队列库中的队列。为此,请创建一个由线程共享的 Queue 实例。然后线程使用 put() 或 get() 操作从队列中添加或删除项目,如下面的代码所示。

    例如,请参阅here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-06
      • 2012-02-27
      • 1970-01-01
      • 2018-07-03
      • 2011-01-19
      相关资源
      最近更新 更多