4

I am losing data on my sockets because I am doing a close().

The Linux-specific shutdown() manpage is not helpful:

The shutdown() call causes all or part of a full-duplex connection on the socket associated with sockfd to be shut down. If how is SHUT_RD, further receptions will be disallowed. If how is SHUT_WR, further transmissions will be disallowed. If how is SHUT_RDWR, further receptions and transmissions will be disallowed.

Microsoft's MSDN is MUCH better, but it being Windows specific, there are differences between it and Linux:

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.

My Question

  • Under Linux, what is the equivalent of waiting for FD_CLOSE (step 1)?

I am getting answers and comments that think I am asking about the behavior on Windows. I am asking about the behavior on Linux, I am merely referencing the Windows documentation because it is much more clear and complete than Linux manpages.

rgettman
  • 176,041
  • 30
  • 275
  • 357
dongle26
  • 826
  • 1
  • 10
  • 18
  • (I assume this is a TCP connection?) Normally all you should need to do is a close(). That will tell the TCP/IP stack to shut down the connection and ensure all data has been delivered. It's possible (likely...) that the process at one end of your conversation is terminating without having read all the incoming data. – Art Swri Oct 10 '12 at 18:32
  • @ArtSwri I come from a Windows background, and at least on Windows, this is not true. Otherwise, what is the purpose of `shutdown()`? If not to properly flush buffers as well as send out a `FIN` instead of a `RST`. – dongle26 Oct 10 '12 at 18:39
  • The purpose of shutdown is to allow you to shut down one side of a TCP conversation while keeping the other open. – Art Swri Oct 10 '12 at 18:42
  • @ArtSwri On Windows this is certainly not the case. Look at the link I've provided to MSDN. The purpose of shutdown is to gracefully close a TCP connection, flushing the buffers, and sending a `FIN`. At least, under Windows. – dongle26 Oct 10 '12 at 18:50
  • 1
    @dongle There's quite a lot of MS documentation that appears to imply that closesocket() doesn't send a FIN, and that you must call shutdown() first, like the link you cited, but closesocket() does send pending data followed by a FIN, unless you have messed with the linger options. The link you cited is about both ends being sure all data has been sent *and received.* – user207421 Oct 11 '12 at 01:53

2 Answers2

5

The MSDN suggestions are followed in my very detailed answer to close() is not closing socket properly. This is essentially the same as Remy Lebeau's answer here.

Community
  • 1
  • 1
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
3

Notice how the Microsoft documentation you quoted says: "One method to wait for notification ..." using WSAEventSelect. That means it is not the only way to do it. The same documentation also describes a similar approach using "overlapped receive calls" via WSARecv() instead. However, a more common (and not event-driven) approach is to call shutdown(), then call recv() in a loop until it returns 0 (graceful disconnect) or SOCKET_ERROR (-1), then call closesocket().

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770