13

I've seen a lot of answers here that say to use close() to destroy a socket but the guide I used from msdn has me using closesocket(). I'm wondering if there is a difference and if there are reasons to use one or the other.

In both cases, I am seeing the suggestion to use shutdown() so that's all well and good.

Enigma
  • 1,247
  • 3
  • 20
  • 51

1 Answers1

22

close() is a *nix function. It will work on any file descriptor, and sockets in *nix are an example of a file descriptor, so it would correctly close sockets as well.

closesocket() is a Windows-specific function, which works specifically with sockets. Sockets on Windows do not use *nix-style file descriptors, socket() returns a handle to a kernel object instead, so it must be closed with closesocket().

I find it rather shameful that BSD-sockets do not include specific counterpart to socket function, which could be used anywhere - but such is life.

The last, but not the least, do not confuse shutdown'ing a socket with closing the socket. shutdown() stops transmission on a socket, but the socket remains in the system and all resources associated with it remain. You still need to close the socket after shutting it down.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • 2
    BSD came first by ten years. They didn't manage to predict the future, but there's nothing shameful about it. – user207421 Feb 16 '16 at 21:39
  • 2
    @EJP, I believe, the good design means that if you have a function to create something, you need to have a function to delete what you created, and not rely on OS-specific implementation details. – SergeyA Feb 16 '16 at 21:48
  • WinSock includes the BSD socket functions, it is just that sockets are not file descriptors on Windows, they are kernel objects, so `close()` cannot be used on sockets in Windows, thus the need for a separate `closesocket()` function instead. – Remy Lebeau Feb 17 '16 at 02:20
  • 2
    @SergeyA I don't know what you're talking about. BSD *is* an operating system, and it reused the existing `close()` function, which already closed file FDs, to also close socket FDs, which in BSD are objects of the same kind. Ten years later Winsock came along and had to add `closesocket()` because Windows socket handles are/were not the same kind of thing as Windows file handles. Why exactly is that BSD's fault, and shameful? – user207421 Feb 17 '16 at 02:57
  • 1
    If BSD added closesocket() to close socket-file-descriptors, for consistency they'd then also want to add closedevice() to close device-file-descriptors, and closepipe() to close pipe-file-descriptors, and closeshmem() to close shared-memory-file-descriptors, and closeserialport() to close serial-port-file-descriptors, and [...] -- or they could just keep the single function close() that works for all file descriptors, and leave inflexible, confusing APIs to the Windows crowd. – Jeremy Friesner Feb 17 '16 at 05:05
  • @JeremyFriesner, I do not see a problem with that. I strongly believe, everything which was created with a specific function, should be closed with the special counterpart function. It makes lives of everybody much easier down the road. But I guess, it wasn't that obvious back than. – SergeyA Feb 17 '16 at 15:19
  • @EJP, see my answer to Jeremy. I believe, good design is to have a pair function to free anything you have created - even if two functions would be the same. It would make supporting and upgrading much less problematic. – SergeyA Feb 17 '16 at 15:21
  • 2
    My experience has been the opposite. I once spent weeks tracking down a nasty resource leak; it turned out that the leak was occurring because a (FILE *) handle that had been created by calling popen() was being closed by calling fclose() (because fclose() was documented as the way to close a (FILE *) when you are done using it) -- but the fclose() call wasn't working because there's actually a separate pclose() call you have to use instead, and that wasn't obvious to the author of the code. The moral: Paired open/close calls only help if any pairing errors are caught at compile time. – Jeremy Friesner Feb 17 '16 at 15:27
  • Of course, the best solution is to have the various open() calls return a reference-counted smart pointer of some sort, so that no explicit corresponding close() call is ever necessary at all -- then it's nearly impossible for the programmer to screw it up. But that isn't practical in C due to lack of ctors/dtors, so it only works if you are writing in C++ and have a C++ wrapper API to use instead. – Jeremy Friesner Feb 17 '16 at 15:30
  • @JeremyFriesner, true and false. I'd rather say, pairing works **best** when errors are caught at compile time - but even without that they are good. Your example is actually about knowing what you are doing :) – SergeyA Feb 17 '16 at 15:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/103746/discussion-between-jeremy-friesner-and-sergeya). – Jeremy Friesner Feb 17 '16 at 15:31
  • @JeremyFriesner, i don't mind returning a resource - anybody can wrap it in deleter if platform supports it. – SergeyA Feb 17 '16 at 15:31
  • @JeremyFriesner, 'd love to, but chat closed from my office. – SergeyA Feb 17 '16 at 15:32