I know there are quite a few SE questions on this, and I believe I read as many of them as it matters before coming to this point.
TIME_WAIT" I mean the state of a server-side socket pair that had its close() initiated on the server side.
I often see these statements that sound contradictory to me:
- You should design your network apps to have clients initiate close(), therefore having client bear the
The reason I find this contradictory is because
TIME_WAIT on the client can be a problem -- the client can run of out available ports, so in essence the above is recommending to move the burden of
TIME_WAIT to the client side where it can be problem, from the server side where it's not a problem.
TIME_WAIT is of course only a problem for limited number of use cases. Most of client-server solutions would involve one server and many clients, clients usually don't deal with high enough volume of connections for it to be a problem, and even if they do, there is a number of recommendations to "sanely" (as opposed to
SO_LINGER with 0 timeout, or meddling with tcp_tw sysctls) combat client-side
TIME_WAIT by avoiding creating too many connections too quickly. But that's not always feasible, for example for class of applications like:
- monitoring systems
- load generators
On the other side, I don't even understand how server-side
TIME_WAIT is helpful at all. The reason
TIME_WAIT is even there, is because it prevents injecting stale
TCP fragments into streams they don't any longer belong to. For client-side
TIME_WAIT it's accomplished by simply making it impossible to create a connection with the same
ip:port pairs that this stale connection could have had (the used pairs are locked out by
TIME_WAIT). But for the server side, this can't be prevented since the local address will have the accepting port, and always will be the same, and the server can't (AFAIK, I only have the empirical proof) deny the connection simply because an incoming peer would create the same address pair that already exists in the socket table.
I did write a program that shows that server-side TIME-WAIT are ignored. Moreover, because the test was done on 127.0.0.1, the kernel must have a special bit that even tells it whether it's a server side or a client side (since otherwise the tuple would be the same).
Source: http://pastebin.com/5PWjkjEf, tested on Fedora 22, default net config.
$ gcc -o rtest rtest.c -lpthread $ ./rtest 44400 s # will do server-side close Will initiate server close ... iterates ~20 times successfully ^C $ ss -a|grep 44400 tcp TIME-WAIT 0 0 127.0.0.1:44400 127.0.0.1:44401 $ ./rtest 44500 c # will do client-side close Will initiate client close ... runs once and then connecting... connect: Cannot assign requested address
So, for server-side
TIME_WAIT, connections on the exact same port pair could be re-established immediately and successfully, and for client-side
TIME-WAIT, on the second iteration
connect() righteously failed
To summarize, the question is two fold:
- Does server-side
TIME_WAITreally not do anything, and is just left that way because the
RFCrequires it to?
- Is the reason the recommendation is for client to initiate close() because the server