You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何停止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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:21:06