Python Socket收到断开消息未关闭致后续代码无法运行求助
问题根因排查
- 主线程被无限阻塞,后续代码永远无法执行
你代码中start()函数内部是while True死循环,且server.accept()是阻塞调用,主线程调用start()后会一直卡在监听新连接的逻辑,永远不会执行到start()之后的my_queue.get()、print(msg)两行代码,这是“后续代码无法运行”的核心原因。 - 连接关闭逻辑存在漏洞,容易出现连接泄漏
当前逻辑只在收到!DISCONNECT!消息时才会关闭连接,如果客户端出现异常断开(比如网络中断、进程崩溃未发送断开消息),conn.recv()会返回空字节,你的代码只判断了if msg_length:,空值会直接跳过判断逻辑,循环会一直空转,不会主动关闭连接。
修复方案
- 将socket服务端监听逻辑放到独立子线程运行,不要阻塞主线程的队列消费逻辑
- 补充异常断开的判断逻辑,只要
recv返回空字节就直接退出循环关闭连接 - 修复日志打印的地址变量错误、替换废弃的API
修复后可正常运行的代码如下:
import threading import queue import socket HEADER = 64 PORT = 6060 SERVER = '0.0.0.0' ADDR = (SERVER, PORT) FORMAT = 'utf-8' DISCONNECT_MESSAGE = "!DISCONNECT!" my_queue = queue.Queue() print(SERVER) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 开启端口复用避免重启服务时端口占用报错 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 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) # 补充判断:recv返回空说明客户端已经主动断开,直接退出循环 if not msg_length: connected = False break msg_length = int(msg_length) msg = conn.recv(msg_length).decode(FORMAT) if msg == DISCONNECT_MESSAGE: connected = False else: my_queue.put(msg) # 打印当前客户端的addr,不是全局服务端ADDR print(f"[{addr}] {msg}") conn.send("MSG Received".encode(FORMAT)) conn.close() print(f"[CONNECTION CLOSED] {addr} 已断开") 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() # 替换已废弃的activeCount为Python3标准API active_count,减去监听线程+主线程得到活跃客户端数 print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}") print("[Starting] Server") # 把服务端监听逻辑放到守护子线程运行,不阻塞主线程 server_thread = threading.Thread(target=start, daemon=True) server_thread.start() # 主线程正常执行队列消费逻辑 while True: msg = my_queue.get() print(f"[QUEUE RECEIVE] {msg}")
内容的提问来源于stack exchange,提问作者Garberchov
相关产品推荐
相关产品推荐

