如何在Python中通过键盘中断终止等待TCP连接的无限循环
解决TCP服务器阻塞在
accept()时无法捕获KeyboardInterrupt的问题 这个问题我太熟悉了!当你的TCP服务器调用accept()进入阻塞状态后,底层的系统调用会“卡住”程序,导致KeyboardInterrupt信号无法被及时捕获,直到有新连接进来才会触发异常处理。下面给你两个实用的解决方案:
方法一:给Socket设置超时时间
通过给监听Socket设置超时时间,让accept()每隔一段时间就跳出阻塞状态,这样循环就有机会检测到KeyboardInterrupt信号。
修改你的可执行代码如下:
# coding=utf-8 from socket import * port = 12000 servername = "127.0.0.1" connection = socket(AF_INET, SOCK_STREAM) connection.bind((servername, port)) connection.listen(1) # 设置1秒超时,你可以根据需求调整时长 connection.settimeout(1) print("SERVER STARTED") while 1: try: x = connection.accept() # 这里可以处理新连接逻辑 print("New connection from", x[1]) except timeout: # 超时后继续循环,不做其他操作 continue except KeyboardInterrupt: print("Keyboard Interrupt Occured") break # 记得关闭socket connection.close() print("I am out of loop")
原理:设置超时后,accept()最多阻塞指定时长,超时会抛出timeout异常,我们捕获后继续循环,这样程序就有机会在每次超时后检查是否有键盘中断信号。
方法二:使用信号处理机制
注册SIGINT信号的处理函数,当按下Ctrl+C时,主动关闭监听Socket,让accept()抛出异常,从而退出循环。
代码示例:
# coding=utf-8 from socket import * import signal import sys port = 12000 servername = "127.0.0.1" connection = socket(AF_INET, SOCK_STREAM) connection.bind((servername, port)) connection.listen(1) # 定义信号处理函数 def handle_interrupt(signum, frame): print("\nKeyboard Interrupt Occured") # 关闭监听socket,让accept()抛出异常 connection.close() sys.exit(0) # 注册SIGINT信号处理 signal.signal(signal.SIGINT, handle_interrupt) print("SERVER STARTED") try: while 1: x = connection.accept() print("New connection from", x[1]) except OSError: # 关闭socket后,accept()会抛出OSError,这里捕获后退出循环 pass print("I am out of loop")
原理:当按下Ctrl+C时,系统会发送SIGINT信号,我们的处理函数会关闭监听Socket,此时阻塞的accept()会立刻抛出OSError,程序就能跳出循环并正常退出。
这两种方法都能解决你的问题,你可以根据自己的业务场景选择:如果需要服务器持续监听且对延迟不敏感,方法一更简单;如果希望立刻响应中断,方法二更高效。
内容的提问来源于stack exchange,提问作者Shubham Nigam
相关产品推荐
相关产品推荐

