Socket.Shutdown VS Socket.Close

close vs shutdown socket?

This is explained in Beej's networking guide. shutdown is a flexible way to block communication in one or both directions. When the second parameter is SHUT_RDWR, it will block both sending and receiving (like close). However, close is the way to actually destroy a socket.

With shutdown, you will still be able to receive pending data the peer already sent (thanks to Joey Adams for noting this).

socket.shutdown vs socket.close

Here's one explanation:

Once a socket is no longer required,
the calling program can discard the
socket by applying a close subroutine
to the socket descriptor. If a
reliable delivery socket has data
associated with it when a close takes
place, the system continues to attempt
data transfer. However, if the data is
still undelivered, the system discards
the data. Should the application
program have no use for any pending
data, it can use the shutdown
subroutine on the socket prior to
closing it.

Why should I use shutdown() before closing a socket?

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 :

  1. Call WSAEventSelect to register for FD_CLOSE notification.
  2. Call shutdown with how=SD_SEND.
  3. 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.
  4. 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 :

  1. Call shutdown with how=SD_SEND.
  2. 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.
  3. 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.

Socket.Disconnect vs Socket.Close

Socket.Close calls Dispose (but it's undocumented).

When using a connection-oriented Socket, always call the Shutdown method before closing the Socket. This ensures that all data is sent and received on the connected socket before it is closed. (msdn)

Your code should looks like this (at least I'd do it like this):

using (var socket = new Socket())
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}

The Disconnect method takes a single parameter bool reuseSocket , according to msdn:

reuseSocket
Type: System.Boolean
true if this socket can be reused after the current connection is closed; otherwise, false.

which basically means, when you set reuseSocket to false it will be disposed after you close it.

The Shutdown method will not disconnect your socket, it will just disable sending/receiving data.

Difference between Socket::close() and StreamSocket::shutdown()

The shutdown function shuts down either the sending side of the connection, the receiving side of the connection, or both. The close function just closes the socket and doesn't necessarily have any effect on the connection. However, if the connection has no references (because you closed the last one), then the operating system will shut down the connection.

Linux: socket close() vs shutdown()

  1. shutdown(sd, SHUT_WR) sends a FIN which the peer responds to with an ACK. Any further attempts to write to the socket will incur an error. However the peer can still continue to send data.

  2. shutdown(sd, SHUT_RD) sends nothing on the network: it just conditions the local API to return EOS for any subsequent reads on the socket. The behaviour when receiving data on a socket that has been shutdown for read is system-dependent: Unix will ACK it and throw it away; Linux will ACK it and buffer it, which will eventually stall the sender; Windows will issue an RST, which the sender sees as 'connection reset by peer'.

Asio end socket functions: cancel, shutdown, close, release

I presume you're talking about a graceful close, i.e. read/write any outstanding data, then close the socket.

The proper steps are:

  1. Call shutdown() to indicate that you will not write any more data to the socket.

  2. Continue to (async-) read from the socket until you get either an error or the connection is closed.

  3. Now close() the socket (in the async read handler).

If you don't do this, you may end up closing the connection while the other side is still sending data. This will result in an ungraceful close.


cancel() and release() aren't the calls you use in a normal flow:

  • cancel() cancels all outstanding asynchronous operations.
  • release() releases ownership of the underlying native socket.


Related Topics



Leave a reply



Submit