如何在python程序中关闭Ctrl-C上的套接字连接

Dav*_*mes 11 python sockets tcp server

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()
Run Code Online (Sandbox Code Playgroud)

KeyboardInterrupt在用Python编写的无限运行的TCP服务器上捕获信号.但是,即使我知道它正在关闭连接,因为它打印Closing Connection,当我尝试重新运行服务器时,我得到:

OSError: [Errno 48] Address already in use

我不知道发生了什么,因为我知道我正在打电话conn.close().

并且运行killall python3没有解决它,我不断得到错误,除非我等待很长时间或更改端口.我也试图grep所有python3进程,但我什么都没得到.

我正在运行OS X Yosemite.

ρss*_*ρss 18

根据文档,错误 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))
Run Code Online (Sandbox Code Playgroud)


bos*_*jak 5

您需要为此注册一个钩子,例如:

#!/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)
Run Code Online (Sandbox Code Playgroud)

  • 如果进程在“conn.recv”上被阻止,则这不起作用。请参阅https://github.com/codypiersall/pynng/issues/49 (3认同)