Prior to VOS 17.1 STCP would not accept a TCP connection request unless the server application had called the accept function. Connection requests were placed in a backlog queue but no response was sent until an accept call removed the request from the backlog queue. Once the backlog queue filled STCP would send a reset in response to a connection request.
Starting in release 17.1 the dynamics of TCP connections have changed. Now when a connection request comes in, assuming that the backlog queue has not been filled, the STCP stack will immediately send a response accepting the connection. The connection is then placed in the backlog queue. Once the backlog queue fills subsequent connection requests are not sent a response. When the server application calls accept the connection at the front of the backlog queue is removed. This behavior is now similar to way that TCP stacks on most other operating systems behave.
Under normal circumstances this change in dynamics will not lead to any noticeable change in the way the server or client applications behave. However, if the server application slows down or connections come in faster than expected, connections may remain in the back log queue for an extended time. Under these circumstances some interesting behaviors may be noticed.
The following table gives a summary of what happens when a connection request is placed in the backlog queue based on the client’s actions. The client may do nothing, waiting for the server application to send data, may send data and/or may close the connection with either a FIN (final) flag (normal close) or RST (reset) flag (abnormal close). The first 4 columns behave as you expect. The server application calls accept getting a socket from the backlog queue then calls recv and either hangs if there is no data or gets data and/or an end of file indication depending on what is in the socket. It is the last 4 columns that need to be looked at more closely.
|Nothing in the socket||Data in the socket||FIN in the socket||Data in the socket/
FIN in the socket
|Data in the socket/
FIN in the socket/
Client socket gone
|FIN in the socket/
Client socket gone
|Data in the socket/
|Accept||Returns socket||Returns socket||Returns socket||Returns socket||Returns socket||Returns socket||Hangs||Hangs|
|First recv||Hangs||Returns data||Returns EOF||Returns data||Returns reset error||Returns EOF|
|Second Recv||Hangs||Returns EOF|
Data in the socket / FIN in the socket / Client socket gone
In this scenario the client has sent some data and shut down the connection. The 17.1 release of STCP will acknowledge all the data that was sent but will not acknowledge the FIN until the data in the receive queue has been handed to the application. As a result the client’s FIN will be retransmitted until the client’s retransmission timer expires. A well written client application will wait for the server application to shut down its side of the connection so when the FIN times out the client will be notified of an error. However if the client application just closes the socket without waiting for an indication from the server it will not know that the data it sent may have been lost.
When the server application calls accept a duplicate acknowledgement packet, acknowledging the data but not the FIN is sent. Since the client has torn down its socket it responds with a reset. The reset clears the socket on the server side. The server application will get a reset error on either the first or second call to recv depending on the time between the call to accept and the call to the first recv. If that time is faster than the time it takes to get and process the client’s reset packet the server application will see the data. In either event the server application will know that a connection has been made and that it was aborted.
FIN in the socket / Client socket gone
This differs from the previous scenario in that there is no data in the socket. When there is no data the FIN is acknowledged. The accept returns the socket and the recv returns an EOF indicating that it has received the FIN. Any attempt to write to the socket, including closing it will result in a reset being returned because the client no longer has the corresponding socket.
Data in the socket / Reset sent
Here the client sends some data and then sends a reset. There can be many reasons for the reset; a common one is the application shutting down the socket and the TCP stack either sending a reset immediately or sending a reset after failing to get an acknowledgment for the FIN packet. This is similar to the first scenario but the client’s TCP stack sends a reset before tearing down its socket instead of just tearing down the socket. Again, a well written client application will see this as an error; a not so well written application will not see an error.
The server socket is torn down and all the data discarded when the reset is received so the server application does not even see an indication that a connection was ever established; it just hangs waiting for another connection.
Again the reset effectively removes the socket from the backlog queue so the accept does not see it and waits for another connection request.
So what does all this really mean? First, client applications may now get a faster connection response but may have to wait longer for any kind of application level banner or message. Any timeouts for this banner/message may need to be adjusted upwards. Second, server applications have to be prepared to handle an error from the recv call immediately after doing an accept. This has always been a possibility but the probability is now greater. Finally, client applications that send data to the server and do not expect any kind of message back should be written to confirm that the server application has correctly shutdown the connection or risk unknowingly loosing data. Again, this possibility has always existed and is not unique to STCP but the probably is now slightly greater.