The answer is in the shutdown()
documentation:
If the how parameter is SD_SEND
, subsequent calls to the send
function are disallowed. For TCP sockets, a FIN
will be sent after all data is sent and acknowledged by the receiver.
...
To assure that all data is sent and received on a connected socket before it is closed, an application should use shutdown
to close connection before calling closesocket
. One method to wait for notification that the remote end has sent all its data and initiated a graceful disconnect uses the WSAEventSelect
function as follows :
- Call
WSAEventSelect
to register for FD_CLOSE
notification.
- Call
shutdown
with how=SD_SEND
.
- When
FD_CLOSE
received, call the recv
or WSARecv
until the function completes with success and indicates that zero bytes were received. If SOCKET_ERROR
is returned, then the graceful disconnect is not possible.
- Call
closesocket
.
Another method to wait for notification that the remote end has sent all its data and initiated a graceful disconnect uses overlapped receive calls follows :
- Call
shutdown
with how=SD_SEND
.
- Call
recv
or WSARecv
until the function completes with success and indicates zero bytes were received. If SOCKET_ERROR
is returned, then the graceful disconnect is not possible.
- Call
closesocket
.
...
For more information, see the section on Graceful Shutdown, Linger Options, and Socket Closure.
In other words, at least for TCP, calling shutdown(SD_SEND)
notifies the peer that you are done sending any more data, and that you will likely be closing your end of the connection soon. Preferably, the peer will also do the same courtesy for you. This way, both peers can know the connection was closed intentionally on both ends. This is known as a graceful disconnect, and not an abortive or abnormal disconnect.
By default, if you do not call shutdown(SD_SEND)
, closesocket()
will attempt to perform a graceful shutdown for you UNLESS the socket's linger option is disabled. It is best not to rely on this behavior, you should always call shutdown()
yourself before calling closesocket()
, unless you have good reason not to.