shutdown()

Hey, I was reading the MSDN docs on shutdown(), and it says this:

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. For example, to initiate a graceful disconnect:

I've never actually used shutdown() before, and my programs seem to be running ok (although, to be sure, they aren't the best either). So what exactly happens if you don't recv() all the data before calling closesocket()? I've always just checked for a recv() returning zero on the other end, to see if the socket has been disconnected, and I haven't ran into any problems yet.

shutdown() allows you to effectivley close half of the connection. For example, a client may send data to a server, then call shutdown() with SD_SEND (Windows). The server will receive all the data, and a second read will get it EOF. From that point on, the server knows it isn't going to get any more data from the client, but the socket is still open, and the server can send data back to the client as normal.

This whole process ensures that no data is lost. This is contrast to the close() method, where the socket is closed in both directions, and the initiator of the close cannot guarantee that it hasn't caused the TCP stack to throw away any data that has not yet been delivered.

There's another important different between close() and shutdown(). Consider when you have more than one reference to a socket, eg a client process that has spawned a child to handle reads, whilst the parent performs the writes. In this case, calls to close() on the socket in one process do not actually close the socket at TCP level. It only stops that one process from reading/writing to it, leaving the other process to go about it's business as normal. Only once the socket reference count reaches 0 will it be closed completely. However, shutdown() affects things at a lower level, and changes all socket references in one go.

and the initiator of the close cannot guarantee that it hasn't caused the TCP stack to throw away any data that has not yet been delivered.

So in other words, say you have a program that connects to a server, sends a bunch of data and then calls close(), some of the data that you want to send to the server might get thrown away 'by accident'?

However, shutdown() affects things at a lower level, and changes all socket references in one go.

So, you mean that while close() only affects i/o on the socket in one process, shutdown() affects it in all processes? Just one thing, how does the TCP implementation know to increase the reference count when you use a socket in a child process?

1. Ok then, so if you're not worried about all the data being received by both sides, then you can use close() without shutdown()? And if you do want all data to be received, you would call shutdown() and wait for the server to close the socket before closing it yourself?

2. That's interesting, but how would the child process even get the socket descriptor, and thus cause the reference count to go up?