I run a particular program on linux which sometimes crashes. If you open it quickly after that, it listens on socket 49201 instead of 49200 as it did the first time. netstat reveals that 49200 is in a TIME_WAIT state.
Is there a program you can run to immediately force that socket move out of the TIME_WAIT state?
Let me elaborate. Transmission Control Protocol (TCP) is designed to be a bidirectional, ordered, and reliable data transmission protocol between two end points (programs). In this context, the term reliable means that it will retransmit the packets if it gets lost in the middle. TCP guarantees the reliability by sending back Acknowledgment (ACK) packets back for a single or a range of packets received from the peer.
This goes same for the control signals such as termination request/response. RFC 793 defines the TIME-WAIT state to be as follows:
See the following TCP state diagram:
TCP is a bidirectional communication protocol, so when the connection is established, there is not a difference between the client and the server. Also, either one can call quits, and both peers needs to agree on closing to fully close an established TCP connection.
Let's call the first one to call the quits as the active closer, and the other peer the passive closer. When the active closer sends FIN, the state goes to FIN-WAIT-1. Then it receives an ACK for the sent FIN and the state goes to FIN-WAIT-2. Once it receives FIN also from the passive closer, the active closer sends the ACK to the FIN and the state goes to TIME-WAIT. In case the passive closer did not received the ACK to the second FIN, it will retransmit the FIN packet.
RFC 793 sets the TIME-OUT to be twice the Maximum Segment Lifetime, or 2MSL. Since MSL, the maximum time a packet can wander around Internet, is set to 2 minutes, 2MSL is 4 minutes. Since there is no ACK to an ACK, the active closer can't do anything but to wait 4 minutes if it adheres to the TCP/IP protocol correctly, just in case the passive sender has not received the ACK to its FIN (theoretically).
In reality, missing packets are probably rare, and very rare if it's all happening within the LAN or within a single machine.
To answer the question verbatim, How to forcibly close a socket in TIME_WAIT?, I will still stick to my original answer:
Practically speaking, I would program it so it ignores TIME-WAIT state using SO_REUSEADDR option as WMR mentioned. What exactly does SO_REUSEADDR do?
I don't know if you have the source code of that particular program you're running, but if so you could just set SO_REUSEADDR via
setsockopt(2)
which allows you to bind on the same local address even if the socket is in TIME_WAIT state (unless that socket is actively listening, seesocket(7)
).For more information on the TIME_WAIT state see the Unix socket FAQ.
As far as I know there is no way to forcibly close the socket outside of writing a better signal handler into your program, but there is a /proc file which controls how long the timeout takes. The file is
and you can set the timeout to 1 second by doing this:
However, this page contains a warning about possible reliability issues when setting this variable.
There is also a related file
which controls whether TIME_WAIT sockets can be reused (presumably without any timeout).
Incidentally, the kernel documentation warns you not to change either of these values without 'advice/requests of technical experts'. Which I am not.
The program must have been written to attempt a binding to port 49200 and then increment by 1 if the port is already in use. Therefore, if you have control of the source code, you could change this behaviour to wait a few seconds and try again on the same port, instead of incrementing.
Actually there is a way to kill a connection - killcx. They claim it works in any state of the connection (which I have not verified). You need to know the interface where communication happens though, it seems to assume eth0 by default.
UPDATE: another solution is cutter which comes in some linux distros' repositories.
Another option is to use the SO_LINGER option with a timeout of 0. This way, when you close the socket is forcibly closed, sending a RST instead of going into the FIN/ACK closing behavior. This will avoid the TIME_WAIT state, and may be more appropriate for some uses.
An alternative solution would be to have some reliable proxy or port forwarding software that listens on port 49200, then forward the connection on to one of several instances of your less reliable program using different ports... HAPROXY springs to mind.
Incidentally the port your connecting on is quite high. You could try using an unused one just above the 0-1024 range. Your system is less likely to use a lower port number as an ephemeral port.
TIME_WAIT is most common issue in socket programming client server architecture. Wait for few seconds trying periodically is the best solution for it. For real time applications they need server must get up immediately There is SO_REUSEADDR option for them.