Networking – How come LAST_ACK doesn’t enter CLOSE_WAIT


When a TCP connection is closed at one end of the connection – the other end receives a FIN and responds with an ACK. This end of the connection then enters the CLOSE_WAIT state. Once close() is called at this end the TCP sends a FIN packet and enters the LAST_ACK state. However, it never enters the TIME_WAIT state.

The TCP State Transition Diagram

Now, let's suppose that the Host A calls close() on the socket and sends a FIN packet to Host B. Host A enters the FIN_WAIT_1 state. Host B receives the FIN packet, sends an ACK and then enters the CLOSE_WAIT state. However, the ACK is dropped somewhere in an upstream router.

Meanwhile, Host B calls close() (recall that Host B is in the CLOSE_WAIT state) and sends a FIN packet to Host A. Host B now enters the LAST_ACK state. Host A receives the FIN packet and replies with an ACK. It then enters the CLOSING state.

At the other end, Host B is still in the LAST_ACK state. It then receives the ACK from Host A and enters the CLOSED state. Recall that the ACK from Host B to Host A was dropped and that Host A has not resent it's FIN packet. Host A resends it's FIN packet on timeout – however Host B has closed the connection.

Is Host A now stuck in the CLOSING state? Can the connection teardown continue? What happens next?

Best Answer

My TCP's a little rusty but I believe it works like this:

When Host B calls close() and sends its FIN, the Sequence number on that FIN will reveal to Host A that it missed a packet from Host B. So Host A won't Ack Host B's FIN, it'll keep Ack'ing the last TCP segment that it successfully received from Host B. This will prompt Host B to retransmit the missing ACK.

So Host A won't reach the CLOSING state, because it won't consider the out-of-order FIN to be truly received until it receives the missing ACK that preceded it.

Related Question