socket.unbind or socket.unlisten? - socket.error: (48, 'Address already in use')
Mark Wooding
mdw at distorted.org.uk
Tue Jan 27 12:05:24 EST 2009
Laszlo Nagy <gandalf at shopzeus.com> writes:
> I have a program that uses socket.bind() and socket.listen()
> frequently. After that program stops, it is not able to bind() again for a
> while:
This is the usual TIME-WAIT problem. The TCP protocol requires one end
of the connection (whichever actually started the close) to keep a
record of it for a while after it closes, in order to avoid confusion
caused by old packets.
> The problem with this, is that this server program SOMETIMES need to be
> restarted very quickly.
The usual solution is to set the SO_REUSEADDR socket option before
binding. This is safe for listening sockets.
Here's an interactive session.
In [1]: import socket as S
In [2]: def make_server_socket():
...: sk = S.socket(S.AF_INET, S.SOCK_STREAM)
...: sk.bind(('', 12345))
...: sk.listen(5)
...: return sk
...:
In [3]: def serve_client(sk):
...: (nsk, addr) = sk.accept()
...: nsk.send('Hello.\n')
...: nsk.close()
...:
In [4]: sk = make_server_socket()
In [5]: serve_client(sk)
(At this point, I connect to the server in another terminal.)
In [6]: sk.close()
In [7]: sk = make_server_socket()
[...]
error: (98, 'Address already in use')
And to confirm that it's TIME-WAIT that's stopping us:
[ponder ~]netstat -n | grep 12345
tcp 0 0 127.0.0.1:12345 127.0.0.1:49988 TIME_WAIT
If I change make_server_socket, then everything works fine.
In [8]: def make_server_socket():
...: sk = S.socket(S.AF_INET, S.SOCK_STREAM)
...: sk.setsockopt(S.SOL_SOCKET, S.SO_REUSEADDR, 1)
...: sk.bind(('', 12345))
...: sk.listen(5)
...: return sk
...:
In [10]: sk = make_server_socket()
In [11]: serve_client(sk)
In [13]: sk.close()
In [14]: sk = make_server_socket()
Done.
If you try this, note that both the old, closed socket /and/ the new one
must have SO_REUSEADDR set on them. If you try this interactively,
you'll have to wait for the non-SO_REUSEADDR socket to leave TIME-WAIT
before you can bind. But once you've done that, it'll work fine from
then on.
-- [mdw]
More information about the Python-list
mailing list