Python中Socket Timeout后线程未正常清理,线程号持续增长的解决方法
问题分析与解决方案
你的代码存在几处导致线程无法正常清理的问题,同时线程ID递增本身是Python的正常行为,但如果是活跃线程数量持续增长,可通过以下方式修复:
1. 捕获Socket超时异常,保证线程正常退出
原代码中recv设置超时后,超时会抛出socket.timeout异常,直接终止线程,导致后续的client_socket.close()和循环退出逻辑无法执行,线程资源无法正常释放。修改on_new_client函数,添加异常捕获:
def on_new_client(client_socket, addr): try: while True: client_socket.settimeout(10) try: data = client_socket.recv(1024).decode('utf-8') except socket.timeout: print(f"Connection from {addr} timed out") break client_socket.settimeout(None) send = "GOK" client_socket.send(send.encode()) if not data: print(f'Disconnected from {addr}') break print("Adr and data", addr, data) finally: # 无论正常退出还是异常,都确保关闭socket client_socket.close() print(f"Connection from {addr} closed")
2. 设置守护线程,避免资源残留
将子线程设置为守护线程,当主线程退出时,所有守护线程会自动终止,防止主线程退出后还有残留线程占用资源。创建线程时添加daemon=True:
thread = Thread(target=on_new_client, args=(c, addr), daemon=True)
注:原代码中thread.join()放在while True循环外,永远不会执行,可直接删除。
3. 使用线程池限制并发数(可选优化)
如果并发连接较多,无限制创建线程会耗尽服务器资源,建议用concurrent.futures.ThreadPoolExecutor管理线程,自动回收线程资源:
import socket from concurrent.futures import ThreadPoolExecutor def on_new_client(client_socket, addr): try: while True: client_socket.settimeout(10) try: data = client_socket.recv(1024).decode('utf-8') except socket.timeout: print(f"Connection from {addr} timed out") break client_socket.settimeout(None) send = "GOK" client_socket.send(send.encode()) if not data: print(f'Disconnected from {addr}') break print("Adr and data", addr, data) finally: client_socket.close() print(f"Connection from {addr} closed") def main(): host = '127.0.0.1' port = 4001 s = socket.socket() s.bind((host, port)) s.listen(5) print(f"Server listening on {host}:{port}") # 创建线程池,设置最大并发线程数 with ThreadPoolExecutor(max_workers=10) as executor: while True: c, addr = s.accept() print("New connection from:", addr) executor.submit(on_new_client, c, addr) if __name__ == '__main__': main()
关于线程号持续增加的说明
Python中线程ID是全局递增的,即使旧线程已被销毁回收,新创建的线程ID也会继续使用下一个数字,这是正常行为,不代表线程资源未被清理。你可以通过threading.enumerate()查看当前活跃线程数量,若数量未持续增长,说明线程已正常清理。
内容的提问来源于stack exchange,提问作者Sathish
相关产品推荐
相关产品推荐

