如何在Python中通过Ctrl+C停止服务器Socket并处理Ctrl+Break
解决服务器监听时无法捕获Ctrl+C及处理Ctrl+Break的方案
问题根源
你的代码里listener.accept()是阻塞式系统调用,在Windows等部分系统中,这种阻塞状态会导致Python无法及时捕获KeyboardInterrupt异常,所以Ctrl+C无法终止程序;而Ctrl+Break在Windows下触发的是SIGBREAK信号,需要手动注册信号处理逻辑才能响应。
解决方案:使用信号处理函数
通过Python的signal模块注册信号处理函数,统一处理Ctrl+C(SIGINT)和Ctrl+Break(SIGBREAK),同时确保退出时正确释放socket资源:
import socket import signal import sys def handle_exit(signum, frame): """统一处理终止信号的函数""" print('\nExiting...') listener.close() sys.exit(0) # 注册信号:Ctrl+C对应SIGINT,Ctrl+Break对应SIGBREAK signal.signal(signal.SIGINT, handle_exit) signal.signal(signal.SIGBREAK, handle_exit) listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) listener.bind(('127.0.0.1', 4444)) listener.listen(0) print('Listening...') try: conn, addr = listener.accept() print(f'Got a connection from {addr}.') conn.close() except Exception as e: print(f'Error occurred: {e}') finally: listener.close()
关键说明
- 信号处理函数会在触发Ctrl/Ctrl+Break时立即执行,即使程序正处于
accept()的阻塞状态。 - 必须手动关闭监听socket,避免端口资源泄漏。
- 这种方式比单纯捕获
KeyboardInterrupt更可靠,能覆盖阻塞调用场景下的信号响应。
进阶:非阻塞监听方案
如果需要更灵活的程序控制,可以将socket设为非阻塞,结合select实现定期检查连接,同时保证信号能及时响应:
import socket import signal import sys import select def handle_exit(signum, frame): print('\nExiting...') listener.close() sys.exit(0) signal.signal(signal.SIGINT, handle_exit) signal.signal(signal.SIGBREAK, handle_exit) listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) listener.bind(('127.0.0.1', 4444)) listener.listen(0) listener.setblocking(False) print('Listening...') while True: # 每1秒检查一次连接状态,期间可响应信号 readable, _, _ = select.select([listener], [], [], 1) if listener in readable: conn, addr = listener.accept() print(f'Got a connection from {addr}.') conn.close()
内容的提问来源于stack exchange,提问作者Sahar
相关产品推荐
相关产品推荐

