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

Windows 10环境下如何通过键盘中断(Ctrl+C)或编程方式关闭Python Socket服务器?

解决Windows下Python Socket服务器无法通过Ctrl+C中断的问题

我之前在Windows上也碰到过一模一样的问题!核心原因是**socket.accept()是阻塞调用**,在Windows系统里,阻塞的socket调用不会响应信号——程序一直卡在accept()那里,根本没机会执行你写的信号处理逻辑,自然没法用Ctrl+C中断。

下面给你两个亲测有效的解决方案:

方案1:给监听Socket设置超时,让循环有机会检查中断信号

给监听Socket加个短超时,这样accept()会定期抛出超时异常,我们就能在异常处理里检查是否收到中断信号,实现优雅退出:

import socket
import sys
import signal

# 全局标志,标记是否需要退出服务器
shutdown_flag = False

def signal_handler(signal, frame):
    global shutdown_flag
    print("\n收到中断信号,正在关闭服务器...")
    shutdown_flag = True

# 注册SIGINT信号处理函数
signal.signal(signal.SIGINT, signal_handler)

host = "127.0.0.1"
port = 9001

# 初始化Socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
# 设置1秒超时,让accept()定期跳出阻塞
s.settimeout(1)

print(f"服务器启动,监听 {host}:{port},按Ctrl+C关闭")

try:
    while not shutdown_flag:
        try:
            # 尝试接受客户端连接
            conn, addr = s.accept()
            print(f"新连接来自 {addr}")
            # 处理客户端请求
            data = conn.recv(1024).decode()
            if data:
                print(f"收到数据:{data}")
            conn.send("Test message from server".encode())
            conn.close()
        except socket.timeout:
            # 超时啥也不用做,只是让循环继续检查shutdown_flag
            continue
finally:
    # 不管程序如何退出,最后都要关闭监听Socket
    print("关闭服务器Socket")
    s.close()
    sys.exit(0)

方案2:用线程拆分逻辑,主线程专门监听信号

把accept()和客户端处理放到子线程里,主线程只负责监听信号,这样信号一来就能立即响应:

import socket
import sys
import signal
import threading

def handle_client(conn, addr):
    """处理单个客户端连接的函数"""
    print(f"新连接来自 {addr}")
    data = conn.recv(1024).decode()
    if data:
        print(f"收到数据:{data}")
    conn.send("Test message from server".encode())
    conn.close()

def server_listen(s):
    """子线程中运行的监听逻辑"""
    while True:
        try:
            conn, addr = s.accept()
            # 每个客户端连接开一个守护线程处理
            client_thread = threading.Thread(target=handle_client, args=(conn, addr))
            client_thread.daemon = True
            client_thread.start()
        except Exception:
            # 服务器关闭时,accept会抛出异常,直接退出循环
            break

def signal_handler(signal, frame):
    """信号处理函数"""
    print("\n收到中断信号,正在关闭服务器...")
    s.shutdown(socket.SHUT_RDWR)
    s.close()
    sys.exit(0)

host = "127.0.0.1"
port = 9001

# 初始化Socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)

# 注册信号处理
signal.signal(signal.SIGINT, signal_handler)

print(f"服务器启动,监听 {host}:{port},按Ctrl+C关闭")
# 启动监听线程
listen_thread = threading.Thread(target=server_listen, args=(s,))
listen_thread.daemon = True
listen_thread.start()

# 主线程阻塞等待,直到收到信号
listen_thread.join()

为什么你的原代码无效?

在Windows系统中,当程序卡在accept()这类阻塞式系统调用时,操作系统不会唤醒阻塞的线程去处理信号——你的程序根本到不了循环里的信号处理逻辑,一直卡在accept()上,自然没法响应Ctrl+C。上面两个方案都是通过“打破阻塞”或者“拆分逻辑”的方式,让程序有机会处理中断信号。

内容的提问来源于stack exchange,提问作者Gary

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:02:44