Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to close socket connection on Ctrl-C in a python programme

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()

I'm catching the KeyboardInterruptsignal here on an infinite-running TCP server I wrote in Python. However, even though I know it is closing the connection because it prints Closing Connection, when I try to re-run the server I get:

OSError: [Errno 48] Address already in use

I have no idea what's happening because I know for sure I'm calling conn.close().

And running killall python3doesn't fix it, I keep getting the error unless I wait for a long time or change port. Also I tried to grep all python3 processes but I get nothing.

I'm running OS X Yosemite.

like image 302
David Gomes Avatar asked Dec 08 '14 14:12

David Gomes


People also ask

Does Ctrl C close sockets?

When you are closing the client using ctrl + c , OS will stop the client process and close all the sockets opened by it.

How do you close a connection in socket programming?

close() call shuts down the socket associated with the socket descriptor socket, and frees resources allocated to the socket. If socket refers to an open TCP connection, the connection is closed. If a stream socket is closed when there is input data queued, the TCP connection is reset rather than being cleanly closed.

Do you need to close socket Python?

There's no need to call s.close() : with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: pass # Use the socket object without calling s.close(). The arguments passed to socket() are constants used to specify the address family and socket type. AF_INET is the Internet address family for IPv4.


2 Answers

As per the docs the error OSError: [Errno 48] Address already in use occurs because the previous execution of your script has left the socket in a TIME_WAIT state, and can’t be immediately reused. This can be resolved by using the socket.SO_REUSEADDR flag.

For eg:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
like image 106
ρss Avatar answered Nov 10 '22 21:11

ρss


You need to register a hook for this, something like:

#!/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)
like image 44
bosnjak Avatar answered Nov 10 '22 23:11

bosnjak