0

I implemented a hello-world like client & echo server on Linux, and used tcpdump to watch the packet exchanges between the two. The server forks a child process on each accepted connection, nothing fancy.

Once the child process serving the connection is killed, the server TCP socket goes into FIN-WAIT-2 (after sending a FIN and receiving the ACK), shown by command ss -tap. ss also shows it is orphaned since the Process column for this entry is empty.

Then I sent one more message from client, it triggers two more TCP messages:

  1. client push the message to server
  2. server respond with a RST

and then ss shows the server socket went missing, I assume it went back to CLOSED state, and got reclaimed.

My question is this: I can understand for an un-orphaned socket, FIN_WAIT_2 can serve the purpose of half-closed connection. But for an orphaned socket, what is the point? Why not go back to CLOSED directly? I read from this post that FIN_WAIT_2 helps to prevent a future connection being mistakenly closed, but if that's the reason, then in my case, the server should NOT close the socket after receiving a regular message - it should wait forever until client sends a FIN, correct?

QnA
  • 1,035
  • 10
  • 25
  • [Connection termination](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination) requires four packets. After one `FIN` and one `ACK` the socket is still technically connected. – user3386109 May 06 '20 at 19:32
  • thanks. I understand the four way connection, and a half-closed connection. My confusion is, for the side that is already orphaned, it can't be reading any new messages anyways, so half-closed status does not apply here. – QnA May 06 '20 at 19:48
  • 1
    Perhaps what you don't realize is that the TCP/IP stack is running independently of any process that you create. Killing the child process notifies the stack that the child is no longer accepting data on a socket. But it doesn't immediately terminate the socket. The stack will still wait to close the connection gracefully. – user3386109 May 06 '20 at 19:48
  • thanks again. Do you mean TCP protocol does not care whether a socket is orphaned? Also, I guess another to ask my question is, why a regular message (without a FIN) from the client make the server FIN_WAIT_2 socket go away? Is that part of TCP protocol? – QnA May 06 '20 at 20:06
  • 1) Yes. 2) `RST` aborts the connection. 3) Yes. Also note that it's not the server that's sending the `RST`. The stack sends the `RST` because the socket was orphaned. That's the key point here, the stack and the server run independently. – user3386109 May 06 '20 at 20:13
  • OK. So for 2), why does the stack on server side wait until the client sent something and then reply with an `RST`? If it knows the socket is orphaned, why not just send `RST` right after the `FIN`/`ACK` cycle? – QnA May 06 '20 at 21:57
  • Server-side stack sends `FIN`. Receives `ACK`. Expects `FIN` from client. Gets data packet from client instead. Sends rude reply to client, and slams the phone down. – user3386109 May 06 '20 at 22:02
  • So far I am with you, if the socket is not orphaned, then I would have no question. But in this case, since socket's owner has died, why expect `FIN` from client, why not just send RST right away and be done with it? – QnA May 06 '20 at 22:12
  • for 3), do you happen to know which kernel function send the `RST` in this case? I traced down to `tcp_rcv_state_process()`, but it seems that without receiving a `FIN` from client, (sk->sk_shutdown & RCV_SHUTDOWN) would be false, hence it won't really send an `RST` yet. Being puzzled by this for a while... – QnA May 06 '20 at 22:14
  • Because TCP guarantees delivery, and RST means that some or all of the data was not delivered. – user3386109 May 06 '20 at 22:17

0 Answers0