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

Posted

技术标签:

【中文标题】如何在 Python 中使用套接字处理多线程?【英文标题】:How to handle multithreading with sockets in Python? 【发布时间】:2021-09-26 05:12:07 【问题描述】:

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

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!

我可以看到这里发生了什么,但我对网络非常陌生,而且我在多线程方面不是很擅长,所以谁能给我一些关于正在发生的事情以及我可以做些什么的见解这些进程是否如我所料同时运行?

【问题讨论】:

总是将完整的错误消息(从单词“Traceback”开始)作为文本(不是截图,不是链接到外部门户)有问题(不是评论)。还有其他有用的信息。 第一次运行没有try/except 的代码,看看你到底得到了什么错误。下次至少使用except Exception as ex: print(ex) 以始终查看有关问题的更多信息。 这是您在服务器中的所有代码吗?错误可能表明它运行了更多的东西 - 一些 recv() 可能等待来自客户端和块服务器的数据 - 其他客户端可能无法连接到服务器。 如果你想和很多客户一起工作,那么在accept()之后你应该使用thread在单独的线程中运行代码——然后主线程可能会回到accept并等待下一个客户。您应该可以在 Internet 上以多种语言找到它。 【参考方案1】:

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)
    

【讨论】:

非常有帮助!谢谢!

以上是关于如何在 Python 中使用套接字处理多线程?的主要内容,如果未能解决你的问题,请参考以下文章

Python 套接字socketserver网络编程

Python Socket接收/发送多线程

在多线程 HTTP 服务器中发送后,如何干净地关闭套接字?

python多线程和套接字连接问题

Python网络编程通过ThreadingMixIn实现多线程异步套接字程序

python 多线程队列套接字