如何停止Python中阻塞在socket.accept()的监听线程?
解决Python线程中socket.accept()阻塞无法停止的问题
方法1:给监听socket设置超时时间
给监听socket设置一个较短的超时时间,让accept()定期抛出超时异常,借此回到循环开头检查data.quit标志,实现及时响应停止信号。
修改后的线程函数代码:
def connection_listener(data:Data=data): logger.info("connection listener thread started") # 设置socket超时时间,比如1秒 data.socket.settimeout(1) while not data.quit: try: socket, address = data.socket.accept() client = Client(socket, address) data.clients.append(client) logger.info(f"client {client.address} connected") socket.send("You are connected to the server".encode(encoder)) except socket.timeout: # 超时仅用于触发循环检查,无需报错 continue except Exception as err: logger.error('listener error: ', err) logger.info("connection listener thread finished") listener_thread = threading.Thread(target=connection_listener) threads.append(listener_thread)
方法2:停止时主动关闭监听socket
当需要停止线程时,主动关闭data.socket,此时阻塞的accept()会立即抛出OSError,捕获后检查data.quit标志即可退出循环。
步骤1:修改线程函数处理socket关闭异常
def connection_listener(data:Data=data): logger.info("connection listener thread started") while not data.quit: try: socket, address = data.socket.accept() client = Client(socket, address) data.clients.append(client) logger.info(f"client {client.address} connected") socket.send("You are connected to the server".encode(encoder)) except OSError as err: # 确认是socket关闭且停止标志已触发时,退出循环 if data.quit: break logger.error('listener socket error: ', err) except Exception as err: logger.error('listener error: ', err) logger.info("connection listener thread finished")
步骤2:在触发停止的逻辑中关闭socket
# 设置停止标志 data.quit = True # 关闭监听socket,打破accept阻塞 data.socket.close() # 等待线程正常结束 listener_thread.join()
方法3:结合threading.Event优化线程安全(可选)
如果觉得自定义quit标志的线程安全性不足,可以用threading.Event替代,核心逻辑仍需结合超时或关闭socket打破accept()阻塞:
# 初始化时用Event替代quit标志 data.stop_event = threading.Event() def connection_listener(data:Data=data): logger.info("connection listener thread started") data.socket.settimeout(1) while not data.stop_event.is_set(): try: socket, address = data.socket.accept() client = Client(socket, address) data.clients.append(client) logger.info(f"client {client.address} connected") socket.send("You are connected to the server".encode(encoder)) except socket.timeout: continue except Exception as err: logger.error('listener error: ', err) logger.info("connection listener thread finished") # 停止线程时 data.stop_event.set() data.socket.close() listener_thread.join()
内容的提问来源于stack exchange,提问作者iamthebull
相关产品推荐
相关产品推荐

