On Linux (my live servers are on RHEL 5.5 – the LXR links below are to the kernel version in that), man 7 ip
says:
A TCP local socket address that has been bound is unavailable for some time after closing, unless the SO_REUSEADDR flag has been set.
I am not using SO_REUSEADDR
. How long is "some time"? How can i found out how long it is, and how can i change it?
I've been googling around this, and have found a few morsels of information, none of which really explain this from an application programmer's perspective. To wit:
- TCP_TIMEWAIT_LEN in
net/tcp.h
is "how long to wait to destroy TIME-WAIT state", and is fixed at "about 60 seconds" - /proc/sys/net/ipv4/tcp_fin_timeout is "Time to hold socket in state FIN-WAIT-2, if it was closed by our side", and "Default value is 60sec"
Where i stumble is in bridging the gap between the kernel's model of the TCP lifecycle, and the programmer's model of ports being unavailable, that is, in understanding how these states relate to the "some time".
Best Answer
I believe that the idea of the socket being unavailable to a program is to allow any TCP data segments still in transit to arrive, and get discarded by the kernel. That is, it's possible for an application to call
close(2)
on a socket, but routing delays or mishaps to control packets or what have you can allow the other side of a TCP connection to send data for a while. The application has indicated it no longer wants to deal with TCP data segments, so the kernel should just discard them as they come in.I hacked out a little program in C that you can compile and use to see how long the timeout is:
I tried this program on 3 different machines, and I get a variable time, between 55 and 59 seconds, when the kernel refuses to allow a non-root user to reopen a socket. I compiled the above code to an executable named "opener", and ran it like this:
I opened another window and did this:
That causes the first instance of "opener" to accept a connection, then close it. The second instance of "opener" tries to
bind(2)
to the TCP port 7896 every second. "opener" reports 55 to 59 seconds of delay.Googling around, I find that people recommend doing this:
to reduce that interval. It didn't work for me. Of the 4 linux machines I had access to, two had 30 and two had 60. I also set that value as low as 10. No difference to the "opener" program.
Doing this:
did change things. The second "opener" only took about 3 seconds to get its new socket.