8

On this MSDN page:

Sending and Receiving Data on the Client

It recommends closing the sending side of the socket by using:

shutdown(SOCK_ID, SD_SEND);

Why should I?

Maybe I dont have to, and its just a recommendation? Maybe its for saving memory? Maybe for speed?

Does anyone have an idea?

user207421
  • 305,947
  • 44
  • 307
  • 483
fdwfg wdfwdfv
  • 229
  • 1
  • 4
  • 9
  • It *might* free up some resources used for sending? At the very least the socket descriptor itself will be free'd up. I don't really see a reason for it though, not in the case of the program you link to. – Some programmer dude Jan 25 '17 at 15:50
  • Your question contains a common, but serious, confusion. You say "it recommends closing down the sending side of the socket". No, it does not. Sockets don't have sides. It recommends closing down the sending side of the *connection* that the socket refers to. Once you realize how important this difference is, you'll see that you have no choice. The `closesocket` function is an operation on a socket, not a connection. If you want to close a connection normally, what alternative do you have? – David Schwartz Jan 26 '17 at 00:09
  • 2
    @Someprogrammerdude The socket descriptor itself will certainly *not* be freed up. Otherwise the following close (a) couldn't possibly work and (b) would be pointless, which it isn't. – user207421 Jan 26 '17 at 00:09
  • @EJP True, must have had a brainfart. – Some programmer dude Jan 26 '17 at 04:21

3 Answers3

7

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.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Actually, `closesocket` will only do it if you're closing the last reference to a connection. If you're trying to shut down the connection, only calling `shutdown` will guarantee that you do it and find out if it worked. The `closesocket` function may succeed and do nothing to the connection at all. – David Schwartz Jan 26 '17 at 00:07
  • @DavidSchwartz: I assume you are referring to multiple references of a connection via use of [`WSADuplicateSocket()`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741565.aspx)? Otherwise, I have no idea what you mean. – Remy Lebeau Jan 26 '17 at 00:10
  • Unless linger is *enabled* with a zero timeout, *or* there is unread pending data in your socket receive buffer. This case of synchronized closes is rather specialized, and not in itself a sufficient reason to recommend `shutdown()` universally. I've never used it. – user207421 Jan 26 '17 at 00:21
  • @RemyLebeau That's the most common way you can wind up with more than one reference to a connection. It can also happen "under the covers" without the application's knowledge. But the point is that `closesocket` is not specified to shut down the connection, just close the socket. – David Schwartz Jan 26 '17 at 00:31
  • 1
    @DavidSchwartz: "*`closesocket` is not specified to shut down the connection*" - the official [documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ms737582.aspx) says otherwise. – Remy Lebeau Jan 26 '17 at 00:41
  • 1
    @DavidSchwartz Under the covers how? Can you give an example? – user207421 Jan 26 '17 at 00:48
  • @EJP What in the documentation do you think says that `closesocket` is going to shut down the connection (other than obvious cases that assume it wasn't duplicated)? There are documented cases of filters and other types of firewall/antivirus type applications duplicating sockets inside a process, causing applications that expected `closesocket` to trigger a clean shutdown to not get the errors they expected. – David Schwartz Jan 26 '17 at 01:03
  • See the fourth paragraph of [this document](https://msdn.microsoft.com/en-us/library/windows/desktop/ms738547.asp) that tries to clear up this confusion. "In Windows Sockets, both the shutdown function, and the WSASendDisconnect function can be used to initiate a shutdown sequence, while the closesocket function is used to deallocate socket handles and free up any associated resources." Regardless, it is trivially observable fact that `closesocket` is not guaranteed to initiate a shutdown of the underlying connection. – David Schwartz Jan 26 '17 at 01:04
  • @DavidSchwartz: that link is broken: "*We're sorry, the page you requested cannot be found.*" – Remy Lebeau Jan 26 '17 at 02:21
  • @RemyLebeau Bummer. Try [https://msdn.microsoft.com/en-us/library/windows/desktop/ms738547(v=vs.85).aspx](https://msdn.microsoft.com/en-us/library/windows/desktop/ms738547(v=vs.85).aspx) – David Schwartz Jan 26 '17 at 02:44
  • 2
    @DavidSchwartz same document that is linked to in my answer. – Remy Lebeau Jan 26 '17 at 03:26
  • @DavidSchwartz Where did I say it would? Why are you even asking? – user207421 Jan 26 '17 at 05:18
  • @EJP I'm just trying to get the false statement at the end of this answer corrected. Read the comment thread from the beginning. – David Schwartz Jan 26 '17 at 05:37
  • @DavidSchwartz But why addess that question to me? I didn't make the statement. – user207421 Jan 26 '17 at 22:17
5

It is unnecessary and redundant except in the following cases:

  1. You want to achieve a synchronized close as described in the documentation quoted by Remy Lebeau.
  2. The socket has been duplicated somehow, e.g. it is shared with child or parent processes or via the API, and you want to ensure the FIN is sent now.
  3. Your application protocol requires that the peer receive a shutdown but needs to continue to send. This can arise for example when writing a proxy server.
  4. You may have unread data in your socket receive buffer and you want to close and ignore it and send a FIN before provoking a connection reset, which will happen when you close if there is unread pending data.

These are the only cases I've ever come across in about 30 years: there may be others but I'm not aware of them.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Don't you pretty much always want to achieve a synchronized close? I don't know that I've ever come across a case where I didn't want a synchronized close. And what about the case where you want to log an error if one occurs during the teardown process? Your answer makes the 95% case sound like the exception! – David Schwartz Jan 27 '17 at 00:47
  • 2
    @DavidSchwartz No, I don't pretty much always want to achieve a synchronised close. I doubt that I've ever either coded one or even seen one, in over 25 years of network programming. HTTP is the most commonly used application protocol on the planet, and it doesn't use one. Neither does TLS. Neither does any other application protocol I've ever looked into. – user207421 Jan 27 '17 at 01:00
  • How do you cleanly shutdown an HTTP connection and log an error if you're unable to on Windows then? You can call `closesocket` and get no error and there's no guarantee the connection was cleanly shut down. – David Schwartz Jan 27 '17 at 01:15
  • 1
    I mean, I've been doing network programming for decades too, and the only cases where I could get away with `closesocket` without `shutdown` for TCP have been toy applications that didn't have to pass any kind of code review or meet any standards that solved one off problems. If nothing else, logging errors is pretty basic, and you just can't do it without calling `shutdown`. How often do you need a "maybe shut the connection down, maybe don't" function?! – David Schwartz Jan 27 '17 at 01:30
  • 1
    @DavidSchwartz Cleanly shutdown HTTP connections are not required by the protocol. HTTP semantics are sufficient: here are the headers, here is the content-length, here is that much response body, or else here is a chunked response, ... end of story, end of transaction. What happens after that I don't care. Especially if it is a connection reset because the user closed the browser page. Not my problem. From the client side I mostly use a connection pool, and as long as I get the response I don't care about a clean shutdown; the connection pool doesn't care either, as it isn't in use anyway. – user207421 Jan 27 '17 at 04:16
  • @MarquisofLorne Can you please explain what #4 means? If you have unread data in your read buffer, sending a shutdown causes it to be ignored but just closing the socket results in some processing of this data? – CaptainCodeman Nov 06 '20 at 21:44
  • @CaptainCodeman If you have unread data in your read buffer and you close the socket, an RST will be issued instead of a FIN. `shutdown()` ensures the FIN is sent before the RST. May not actually help in the end, and you should always read all the data anyway. – user207421 Nov 08 '20 at 02:52
2

There are no specific resources associated with sending or receiving operation on the socket, the socket is either used or closed. There reason for shutdown is not related to resource-management. Shutting down the socket is implementation of so-called graceful shutdown protocol, which allow both sides of the communication to realize the connection is going down and allows to minimize loss of data.

SergeyA
  • 61,605
  • 5
  • 78
  • 137