如何在 Python 中使用套接字处理多线程?

How to handle multithreading with sockets in Python?

我目前正在处理一个问题,我需要让一个服务器同时处理多个客户端。我有一个 server.py 文件和一个 client.py 文件。这是来自 server.py 的片段:

connections = []
addresses = []

for c in connections:
    c.close()
del connections[:]
del addresses[:]  #clears anything pre-existing

while True:
    try:
        csock, address = s.accept() #takes in connection and stores info
        s.setblocking(1) #prevents timeout
        connections.append(csock)
        addresses.append(address)
        print(f"Connection from {address} has been established!")
    except:
           print("Error has occurred")


当我 运行 我的服务器在终端中,然后用客户端连接到它。它的行为如我所料,打印出 Connection from ('192.168.1.84', 50824) has been established!.

当我打开另一个终端并 运行 client.py 建立额外的连接时,没有任何反应。也就是说,直到我关闭我的第一个客户端进程然后服务器打印出

Error occurred
Connection from ('192.168.1.84', 50826) has been established!

我大概能看到这里发生了什么,但我对网络还很陌生,而且我在多线程方面也不是很擅长,所以谁能给我一些关于发生了什么以及我能做什么的见解像我期望的那样同时进行这些过程 运行?

s.accept() 之后,您应该在单独的线程中使用 threading 到 运行 代码 - 这个线程应该继续与客户端连接。同时主线程可能会返回s.accept()等待下一个客户端。


具有一些额外设置的最小工作代码。

服务器:

import socket
import threading
import time

# --- functions ---

def handle_client(conn, addr):
    print("[thread] starting")

    # recv message
    message = conn.recv(1024)
    message = message.decode()
    print("[thread] client:", addr, 'recv:', message)
    
    # simulate longer work
    time.sleep(5)

    # send answer
    message = "Bye!"
    message = message.encode()
    conn.send(message)
    print("[thread] client:", addr, 'send:', message)
    
    conn.close()

    print("[thread] ending")
   
# --- main ---

host = '0.0.0.0'
port = 8080

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # solution for "[Error 89] Address already in use". Use before bind()
s.bind((host, port))
s.listen(1)

all_threads = []

try:
    while True:
        print("Waiting for client")
        conn, addr = s.accept()
    
        print("Client:", addr)
        
        t = threading.Thread(target=handle_client, args=(conn, addr))
        t.start()
    
        all_threads.append(t)
except KeyboardInterrupt:
    print("Stopped by Ctrl+C")
finally:
    if s:
        s.close()
    for t in all_threads:
        t.join()
    

客户端(用于测试)

import socket

# --- main ---

host = '0.0.0.0'
port = 8080

s = socket.socket()
s.connect((host, port))

print("Connected to the server")

message = "Hello"
print('send:', message)
message = message.encode()
s.send(message)

message = s.recv(1024)
message = message.decode()
print('recv:', message)