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

时间:2014-12-08 14:30:14

标签: 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()

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

OSError: [Errno 48] Address already in use

我不知道发生了什么,因为我肯定知道我正在呼叫conn.close()

运行killall python3无法解决问题,除非我等待很长时间或更改端口,否则我会继续收到错误消息。此外,我试图grep所有python3进程,但我什么都没得到。

我正在运行OS X Yosemite。

2 个答案:

答案 0 :(得分:16)

根据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))

答案 1 :(得分:4)

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

#!/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)