closesocket()
PROTOTYPE
#include <sockets.h>
int closesocket(int socket);
DESCRIPTION
closesocket() frees the socket control block referenced by socket, a handle returned by accept() or socket(). It closes the socket connection, if one exists, and recovers socket resources. For UDP sockets, closesocket() is always non-blocking. It frees socket resources and returns.
For TCP sockets, closesocket() is non-blocking by default. It marks the socket as unavailable for further application use and returns immediately. If there is unsent or unacknowledged data, TCP waits until the data has been sent and acknowledged before closing the connection by exchanging FIN flags with the connected peer. This is called a graceful close.
The default TCP behavior can be modified by the setsockopt() linger option. This option takes a pointer to a variable of the following type:
struct linger
{
int l_onoff; /* linger option on/off */
int l_linger; /* linger time (seconds) */
}
If l_onoff and l_linger are non-zero, closesocket() waits up to l_linger seconds for its sent FIN to be acknowledged by the peer. If this is not received in time, closesocket() returns -1 with errno set to EWOULDBLOCK. The graceful close continues after a linger timeout. If acknowledgment is never received, TCP resends FIN multiple times and waits up to eight minutes before dropping the connection and sending RST.
If acknowledgment arrives before linger times out, closesocket() returns 0, confirming that the graceful close was successful. If RST arrives during the linger wait, it resets the connection and closesocket() returns -1 with errno set to ECONNRESET. If this occurs after the linger timeout, the API is not notified that the connection was forcibly reset. One reason to linger is to get status information about the close.
If l_onoff is non-zero and l_linger is zero, closesocket() performs a forceful close by immediately sending RST to the connected peer and dropping the connection. Note: a forceful close is also done if the socket holds unread received data when closesocket() is called.
It is a programming error to request linger if the socket has been set to non-blocking mode. In that case, closesocket() immediately returns -1 with errno set to EWOULDBLOCK and a graceful close is performed.
If closesocket() is called and the peer acknowledges our FIN but never sends its own, our socket control block could be tied up indefinitely. In this case, TargetTCP waits two minutes before dropping the connection and sending RST to the peer. This timeout does not apply if shutdown() is used to send a FIN that is acknowledged by the peer. In that case, the socket handle is still available and can be used to read data sent by the peer.
If successful, closesocket() returns 0. Otherwise, it sets errno and returns -1.
ERROR CODES
| ECONNRESET | Connection was forcibly closed by the peer during a lingering close. |
| EINPROGRESS | A TCP graceful close is already in progress. |
| ENETDOWN | TargetTCP has not been initialized. |
| ENOTSOCK | socket is not a valid socket handle. |
| EWOULDBLOCK | A lingering wait timed out before our FIN was acknowledged or a non-zero linger timeout was used on a non-blocking socket. |
EXAMPLE
struct linger ling;
/*-------------------------------------------------------------------*/
/* Perform a forceful close. */
/*-------------------------------------------------------------------*/
ling.l_onoff = TRUE;
ling.l_linger = 0;
setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
if (closesocket(sock))
perror("closesocket() failed");