如何在 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 上的套接字连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 中关闭浏览器上的会话

如何在 macOS 中关闭 OpenCV 窗口(Python 3)?

在 python 的运行脚本中关闭 GPU

在 Kotlin 中关闭应用程序后,如何将 onItemSelected 保留在选中的同一项目上?

如何让线程等待 JFrame 在 Java 中关闭?

如何从代码中关闭 Java Swing 应用程序