Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python socket doesn't close connection properly

I am new to socket programming and ran into a puzzling problem:

I have a windows program which I cannot alter (proprietary software) but which tries to connect to a specific ip and port with a tcp socket.

On my linux box I wrote a little python script to serve the socket to the win prog. This works fine until I kill my prog on linux. The initial server socket doesn't close as specified and I cannot restart my program until the socket is garbage collected.

If I try the same with a linux socket (in a seperate python script) I have no problems.

Here is a minimal code example:

import socket

server = socket.socket()
server.bind(('192.168.0.111', 50001))
server.listen(1)
conn, addr = server.accept()
print 'Connection established'

running = True
while running:
    try:
        data = conn.recv(4096)
    except KeyboardInterrupt:
        conn.close()
        running = False
    else:
        if data:
            print data
        else:
            conn.close()
            running = False
server.close()

If I kill this with Ctrl-C it exits normally. But upon restarting the script I get a socket.error stating the address is already in use. After a minute or so the program works again.

I also tried a shutdown before the close (aka conn.shutdown(2) and server.shutdown...) but that has no effect.

Is there a better 'right' way to close a windows socket? Do I miss something fundamental about sockets in general?

Thanks!

edit: I think I just saw the answer here: what is the correct way to close a socket in python 2.6?

Although I'm using python 2.5 it might still work.

like image 815
BandGap Avatar asked Feb 18 '11 11:02

BandGap


2 Answers

You are experiencing the TIME_WAIT state of connected sockets. Even though you've closed your socket, it still has lingering consequences for a couple minutes. The reasons for this, as well as a socket flag you can set to disable the behavior (SO_REUSEADDR), are explained in the UNIX guide socket FAQ.

In short,

server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(...)
...
like image 157
Jean-Paul Calderone Avatar answered Nov 03 '22 00:11

Jean-Paul Calderone


Try adding import sys and terminating your app with sys.exit(). The socket stays reserved until the system is satisfied that the application is closed. You can be explicit about that with sys.exit()

[edit]Oh, ok. I am pretty new to sockets myself. So you are saying that this sequence is not safe? I cant imagine any other way to do it. You have to close your app at some point, with some technique, right? How is it correctly done then?

server.shutdown(socket.SHUT_RDWR) 
server.close()
sys.exit()
like image 41
Alan Avatar answered Nov 03 '22 00:11

Alan