如何在 python 程序中关闭 Ctrl-C 上的套接字连接
Posted
技术标签:
【中文标题】如何在 python 程序中关闭 Ctrl-C 上的套接字连接【英文标题】:How to close socket connection on Ctrl-C in a python programme 【发布时间】:2015-02-06 05:45:20 【问题描述】:s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
any_connection = False
while True:
try:
conn, addr = s.accept()
data = conn.recv(1024)
any_connection = True
# keep looking
if not data: continue
pid = os.fork()
if pid == 0:
server_process(data, conn)
except KeyboardInterrupt:
break
if any_connection:
print("Closing connection")
conn.close()
我在我用 Python 编写的无限运行 TCP 服务器上捕获了KeyboardInterrupt
信号。但是,即使我知道它正在关闭连接,因为它打印 Closing Connection
,当我尝试重新运行服务器时,我得到:
OSError: [Errno 48] Address already in use
我不知道发生了什么,因为我确定我在打电话给conn.close()
。
并且运行killall python3
并没有修复它,除非我等待很长时间或更改端口,否则我会不断收到错误消息。我也尝试 grep 所有python3
进程,但我什么也没得到。
我正在运行 OS X Yosemite。
【问题讨论】:
您确定错误代码是 48 而不是 98? 【参考方案1】:您需要为此注册一个钩子,例如:
#!/usr/bin/env python
import signal
import sys
def signal_handler(signal, frame):
# close the socket here
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
【讨论】:
如果进程在conn.recv
上被阻止,这将不起作用。请看github.com/codypiersall/pynng/issues/49【参考方案2】:
根据docs 错误OSError: [Errno 48] Address already in use
发生是因为
您的脚本的先前执行使套接字处于 TIME_WAIT 状态,并且不能立即重用。这可以通过使用socket.SO_REUSEADDR
标志来解决。
例如:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
【讨论】:
以上是关于如何在 python 程序中关闭 Ctrl-C 上的套接字连接的主要内容,如果未能解决你的问题,请参考以下文章
如何在 macOS 中关闭 OpenCV 窗口(Python 3)?