Python异步处理Socket阻塞:实现等待连接时运行等待动画
解决Socket阻塞期间显示等待动画的问题
环境
- Windows 11
- Python 3.11.3
现有代码
等待动画函数
def waiting(): while True: for i in range(3): print("Waiting") time.sleep(1) os.system('cls') print("Waiting.") time.sleep(1) os.system('cls') print("Waiting..") time.sleep(1) os.system('cls') print("Waiting...") time.sleep(1) os.system('cls')
Socket连接函数
def succesful_connect(): host = socket.gethostname() port = 5000 your_host = socket.gethostname() your_host=socket.gethostbyname(your_host) print('Your IP:', your_host) server_socket = socket.socket() server_socket.bind((host, port)) server_socket.listen(2) conn, address = server_socket.accept() return conn, address
问题
代码中conn, address = server_socket.accept()会完全阻塞程序,直到有连接建立,这段时间内无法执行任何其他操作。之前尝试编写等待循环,但无法在连接成功后停止循环,希望通过异步方式让waiting()循环显示等待动画,直到连接成功建立。
解决方案
使用Python的threading模块将Socket连接逻辑放到子线程执行,主线程负责运行等待动画。通过全局标志和队列同步连接状态与传递连接对象,实现动画与连接的并行执行。
修改后的完整代码
import time import os import socket import threading from queue import Queue # 用于传递连接结果的队列 result_queue = Queue() # 标记是否已成功建立连接 connected = False def waiting(): while not connected: # 循环显示等待动画,用\r覆盖当前行减少闪屏 for suffix in ["", ".", "..", "..."]: if connected: break print(f"Waiting{suffix}", end="\r") time.sleep(0.5) os.system('cls') def successful_connect(): global connected host = socket.gethostname() port = 5000 your_host = socket.gethostbyname(socket.gethostname()) print('Your IP:', your_host) server_socket = socket.socket() server_socket.bind((host, port)) server_socket.listen(2) # 等待客户端连接 conn, address = server_socket.accept() # 连接成功后更新状态 connected = True print(f"\n已成功连接到客户端:{address}") # 将连接对象存入队列 result_queue.put((conn, address)) if __name__ == "__main__": # 启动Socket连接子线程 connect_thread = threading.Thread(target=successful_connect) connect_thread.start() # 主线程运行等待动画 waiting() # 从队列获取连接结果 conn, address = result_queue.get() # 后续可在此处处理连接(示例:接收客户端消息) data = conn.recv(1024).decode() if data: print(f"收到客户端消息:{data}") # 关闭连接 conn.close()
代码说明
- 线程分离:将Socket连接逻辑放入子线程,避免
accept()的阻塞特性影响主线程的动画显示。 - 状态同步:通过全局变量
connected标记连接状态,主线程的等待动画循环会实时检查该变量,一旦连接成功就停止动画。 - 流畅输出:使用
end="\r"覆盖当前行输出,替代频繁调用os.system('cls'),减少屏幕闪烁。 - 结果传递:利用
Queue安全传递连接后的conn和address对象,避免全局变量的线程安全问题。
内容的提问来源于stack exchange,提问作者VANECK
相关产品推荐
相关产品推荐

