Monthly Archives: July 2009

SO_REUSEADDR

Dear Lazyweb,

I have a simple test application where a TCP/IP server listens for incoming connections, reads the data and closes the connection again and a client which opens connections to the server and sends a package and closes the connection as fast as it can:

The server looks like this:

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setblocking(False)
    sock.bind(("", 12347))
    sock.listen(1)

    slist = [sock]
    # use select to poll the sockets
    while 1:
        l = select.select(slist, [], [])
        for i in l[0]:
            conn, addr = i.accept()
            data = ""
            while 1:
                tmp = conn.recv(1024)
                if not tmp:
                    break
                data += tmp
            conn.shutdown(socket.SHUT_RDWR)
            conn.close()

The Client:

    # Open a connection, send data and close the connection as fast as possible
    while 1:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect(("", 12347))
        sock.send("foo")
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()

The Problem with this application: After roughly 25.000 Iterations the client quits with a friendly:

error: (99, ‘Cannot assign requested address’)

Netstat shows the problem: roughly 25.000 of these ones:

...
tcp        0      0 localhost:56946   localhost:12347         TIME_WAIT
tcp        0      0 localhost:47163   localhost:12347         TIME_WAIT
tcp        0      0 localhost:42758   localhost:12347         TIME_WAIT
...

I’m not a TCP/IP expert but I thought SO_REUSEADDR is supposed to address this problem by allowing to reuse those as-good-as-closed connections in TIME_WAIT state, or not? So why does it fail in my test application?