22

I am a bit confused by the cornucopia of related methods on the Socket object that supposedly close and clean up a socket connection. Consider the following:

var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("192.168.1.22", 8333);
socket.Send(Encoding.UTF8.GetBytes("hello"));

// now for the closing fun
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Close();
socket.Dispose();

In addition, this guy says that to really cleanly close a connection, one must execute socket.Shutdown(SocketShudown.Send), then wait for the other side to respond.

What is the correct way to close, then clean up a socket connection?

AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • That guy is half right. I think it depends on the protocol between the two. If you are expecting to still be able to receive for some time then yes, you should tell the otherside of your intent to shutdown and say that you will stop sending but can still receive. – uriDium Mar 12 '13 at 07:20
  • "that guy" is mostly correct, as I have modeled my server code similarly. But I believe the half-close-then-wait approach is only necessary for asynchronous (non-blocking) sockets. I believe in the case of non-blocking sockets, you call "Send" followed immediately by Close, there are some edge conditions in which data loss can occur if there are packets that need to be retransmitted. – selbie Mar 12 '13 at 08:40
  • I used a hybrid approach with my socket server. The server will half-close the connection first and wait for recv() to return 0 or error to indicate the client is done. However, I have a timer that periodically goes off every 45 seconds to sweep and close any half-open connections that have been lingering around since the last sweep. – selbie Mar 12 '13 at 08:42
  • Any way of doing this usin TcpClient ? – eran otzap Jul 09 '17 at 16:10

2 Answers2

18

Closing socket closes the connection, and Close is a wrapper-method around Dispose, so generally

socket.Shutdown(SocketShutdown.Both);
socket.Close();

should be enough. Some might argue, that Close implementation might change one day (so it no longer calls Dispose), and you should call Dispose manually after calling Close, but i doubt thats gonna happen, personally :)

Alternatively, consider using using (yeh):

using (var socket = new Socket(...))
{
    ....
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();
}
Kelly Elton
  • 4,373
  • 10
  • 53
  • 97
Nikita B
  • 3,303
  • 1
  • 23
  • 41
1

According to MSDN, for connection-oriented sockets, if you call Connect, you should call Close. This applies to BeginConnect and ConnectAsync as well.

using (var socket = new Socket(...)) {
    socket.Connect(host);
    ...
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();
}
Kelly Elton
  • 4,373
  • 10
  • 53
  • 97