Hi @oberondoro, thank you for reporting this.
You should be able to post links by now.
We are not aware that the +TCP library has or had a problem with “hanging sockets”.
Somewhere in the code I read:
/* And wait for the user to close this socket. */
vTCPStateChange( pxSocket, eCLOSE_WAIT );
Which says that the eCLOSE_WAIT
state must be handled by the owner of the socket.
@oberondoro wrote:
Is there another way to safely close these sockets or another way to solve the problem?
Can I directly check the socket state and close it if “eCLOSE_WAIT”?
Yes, if you are sure that the socket won’t be referred to by your application or by the HTTP library, you can call closesocket()
to delete the socket.
Here below I will describe how this normally happens:
When a TCP API returns a negative number, it contains an errno value.
Most negative codes are fatal errors, except for pdFREERTOS_ERRNO_EAGAIN
(AKA pdFREERTOS_ERRNO_EWOULDBLOCK
) and pdFREERTOS_ERRNO_EINTR
.
This is a simple TCP echo server:
for( ;; )
{
BaseType_t xRc = FreeRTOS_recv( xSocket, pcBuffer, sizeof pcBuffer, 0 );
if( xRc > 0 )
{
xRc = FreeRTOS_send( xSocket, pcBuffer, ( size_t ) xRc, 0 );
}
if( xRc < 0 )
{
if( ( xRc != -pdFREERTOS_ERRNO_EAGAIN ) &&
( xRc != -pdFREERTOS_ERRNO_EINTR ) )
{
printf("The connection is broken with errno %d\n", -xRc );
break;
}
}
}
/* The socket will be deleted. */
FreeRTOS_closesocket( xSocket );
Note that in the above example there is no need to call shutdown()
. The peer already took the initiative to shutdown the connection.
Some users are confused about the use of shutdown()
. HTTP servers are usually passive, they will only close a socket when the connection got disrupted, as in the above example.
I am not sure who is responsible to close a connection when using REST-API, but if you need to close a connection actively (and gracefully), the following can be done:
/* Start closing the connection: */
FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
for( ;; )
{
BaseType_t xRc = FreeRTOS_recv( xSocket, pcBuffer, sizeof pcBuffer, 0 );
if( xRc > 0 )
{
/* Very important: handle the last bytes received. */
}
else if( xRc < 0 )
{
if( ( xRc != -pdFREERTOS_ERRNO_EAGAIN ) &&
( xRc != -pdFREERTOS_ERRNO_EINTR ) )
{
printf("The shutdown is acknowledged by the peer (errno %d)\n", -xRc );
break;
}
}
}
/* Close ( free ) the socket. */
FreeRTOS_closesocket( xSocket );
In other words, call shutdown()
once, wait until an API call (like recv()
returns a fatal code, and close the socket.