Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TCP - What if client call close() before server accept()

In C/C++, if client and server finished 3-way handshake and this connection was sitting in server's backlog (listening queue). Before server calls accept(), what gonna happen if client calls close(). Will this connection get removed from backlog?

The real world situation is that, server sometimes is too busy to accept every connection immediately. So there will be some connections waiting in backlog. The client has a timeout for the first response from server. If the timeout happens, it will call close() then retry or whatever. At this moment, I am wondering if the backlog of server will remove the connection from backlog.

Please share your idea. Appriciate it!

like image 503
Renjie Zhang Avatar asked Jul 31 '20 04:07

Renjie Zhang


People also ask

What happens if you run TCP client before TCP server?

a) If you run TCPClient first, then the client will attempt to make a TCP connection with a non- existent server process. A TCP connection will not be made.

What happens when client closes socket?

The Session and Subscription timeouts exists to give clients time to recover when communication is interrupted. So closing a socket without calling CloseSession means the timeouts need to be honoured because the Server cannot know if it was a network issue and the Client intends to reconnect or if it is gone forever.

What happens when TCP closes a connection?

Figure 214: TCP Connection Termination ProcedureThe server waits for the server process to be ready to close and then sends its FIN, which is acknowledged by the client. The client waits for a period of time to ensure that its ACK is received, before proceeding to the CLOSED state.

Should the server or client close the connection?

Either end may close the connection - neither is "more correct". However, it is important to clear up one (seeming) misunderstanding in your code: closing the ServerSocket is not closing the socket that represents the connection between the two end points. The ServerSocket is a listening socket on a port.


1 Answers

Generally speaking, if a client calls close(), the clients protocol stack will send a FIN to indicate that the client is done sending, and will wait for the server to send a FIN,ACK back to the client (which won't happen before the server accepts the connection, as we shall see), and then the client will ACK that. This would be a normal termination of a TCP connection.

However, since a TCP connection consists of two more or less independent streams, sending a FIN from the client really is only a statement that the client is done sending data (this is often referred to as "half closed"), and is not actually a request at the TCP protocol level to close the connection (although higher level protocols often will interpret it that way, but they can only do so after the connection has been accepted and they have had a read return 0 bytes in order to learn that the client is done writing). The server can still continue to send data, but since the client has called close(), it is no longer possible for this data to be delivered to the client application. If the server sends further data, the protocol stack on the client will respond with a reset, causing an abnormal termination of the TCP connection. If the client actually wished to continue receiving data from the server after declaring that it was done sending data, it should do so by calling shutdown(sock,SHUT_WR) rather than calling close().

So what this means is that the connections that time out and that are normally closed by clients will generally remain active at the server, and the server will be able to accept them, read the request, process the request, and send the reply and only then discover that the application can no longer read the reply when the reset is returned from the client. The reason I say "generally" is that firewalls, proxies, and OS protocol stacks all place limits on how long a TCP connection can remain in a half closed state, generally in violation of the relevant TCP RFCs but for "valid" reasons such as dealing with DDOS.

I think your concern is that a server that is overloaded will be further overloaded by clients timing out and retrying, which in my view is correct based on my preceding explanation. In order to avoid this, a client timing out could set SO_LINGER to 0 prior to calling close() which would cause a reset to be sent to cause an immediate abnormal termination. I would also suggest using an exponential back-off on timeout to further mitigate the impact on an overloaded server.

like image 85
Jim D. Avatar answered Sep 19 '22 23:09

Jim D.