1

When using blocking sockets and the recv() function, when the socket has received a FIN packet, recv() will return 0.

However, how to know when the socket has received a FIN packet when using WSARecv() and IOCP? I think that the lpNumberOfBytesRecvd will also be set to 0, but I'm not sure.

1 Answers1

1

If the WSARecv() call is in progress when the FIN arrives then you will get a successful completion with lpNumberOfBytesRecvd set to 0.

If the WSARecv() call is initiated after the FIN arrives then you may get a WSAESHUTDOWN error from the WSARecv() call.

I tend to issue a shutdown(s, SD_RECEIVE) on the socket when I get the first 'client close' (i.e. zero byte read return) as this then gives the predictable behaviour above and avoids a trip through the IOCP for subsequent attempts to receive...

Len Holgate
  • 21,282
  • 4
  • 45
  • 92
  • What will be the error code when `WSARecv()` returns an error (i.e. what will `WSAGetLastError()` return)? –  Mar 06 '15 at 13:51
  • 1
    In the case where a completion is issued, if the peer disconnects gracefully (sends `FIN`) then I/O success of 0 bytes is reported. But if the connection is lost abnormally then I/O failure with an error code is reported, such as `ERROR_NETNAME_DELETED` (64). Make sure you are accounting for socket failures and abnormal disconnects. Not all clients disconnect gracefully, or network mishaps might sometimes lose the `FIN`. – Remy Lebeau Mar 06 '15 at 19:04
  • 1
    Yes, but that wasn't what the question was about. :) There are lots of ways for a completion to fail... This isn't actually the failure path, it's the success path with a 0 byte read. – Len Holgate Mar 06 '15 at 21:39
  • I have called `WSARecv()` after a FIN packet has been arrived, and `WSARecv()` has returned `0`, and `WSAGetLastError()` has also returned `0`! –  Mar 07 '15 at 15:55
  • Er, if `WSARecv()` returns success (0) then a completion will be queued, deal with it there. My code to handle `WSAESHUTDOWN` explicitly for `WSARecv()`s as a 'client close' may come from the fact that I explicitly call shutdown(recv) when I get a client close from any `WSARecv()` this guarantees easy to understand behaviour from subsequent `WSARecv()` calls that are issued after this point and avoids the context switch to the IOCP thread to deal with it... – Len Holgate Mar 07 '15 at 16:12
  • 1
    @RemyLebeau The FIN is subject to acknowledgement and retransmission just like a TCP data segment. – user207421 Mar 07 '15 at 18:34
  • @LenHolgate: you can optionally use `SetFileCompletionNotificationModes()` to request `FILE_SKIP_COMPLETION_PORT_ON_SUCCESS` if you want to deal with success at the call site rather than in the IOCP queue. – Remy Lebeau Mar 07 '15 at 19:11
  • @EJP: I am aware of that, but that is still no guarantee that it can never be lost. – Remy Lebeau Mar 07 '15 at 19:12
  • If it's lost then it fails to comply with the questioner's criteria ("how to know when the socket has received a FIN packet") as it wasn't received. It simply becomes an error condition... – Len Holgate Mar 08 '15 at 21:43