Hi.
I'm new to WinSock, so please, be patient ;)

I found a dicrepancy in MSDN considering shutdown() and FD_CLOSE notification (from WSAsyncSelect doc)
The sequence from shutdown() doc is

1 Call WSAAsyncSelect to register for FD_CLOSE notification.
2 Call shutdown with how=SD_SEND.
3 When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR.
4 Call closesocket.

I'm using message notification sockets. So I'm always catching FD_CLOSE
from WSAsyncSelect doc:

WSAsyncSelect doc, FD_CLOSE description

FD_CLOSE: Only valid on connection-oriented sockets (for example, SOCK_STREAM)
1.
when WSAAsyncSelect called, if socket connection has been closed,
2.
after remote system initiated graceful close, when no data currently available to receive (note: if data has been received and is waiting to be read when the remote system initiates a graceful close, the FD_CLOSE is not delivered until all pending data has been read),
3.
after local system initiates graceful close with shutdown and remote system has responded with "End of Data" notification (for example, TCP FIN), when no data currently available to receive,
4.
when remote system terminates connection (for example, sent TCP RST), and lParam will contain WSAECONNRESET error value.


It seems, at least for the case #2 there is no need to call recv after
receiving FD_CLOSE since all FD_READ message are delivered by this time.

I'm not sure for other case, but when I call recv I get 0.
So, in which cases is it really necessary to loop with recv (especially when I don't expect anything else from the remote site and have one thread )?
Posted on 2002-12-05 17:13:34 by Sergo
It seems, at least for the case #2 there is no need to call recv after
receiving FD_CLOSE since all FD_READ message are delivered by this time.


This is true, no more FD_READ messages will be received and the socket will not accept incomming packets after FD_CLOSE is received. It is pointless to try to receive packets on this socket after receiving an FD_CLOSE message because you will NEVER get anything! (However in the graceful shutdown method using shutdown() you can still send data to the client)

So, in which cases is it really necessary to loop with recv (especially when I don't expect anything else from the remote site and have one thread )?


Using shutdown initiates a "graceful shutdown"! I recomend you read the microsoft documentation on Graceful shutdowns! If you do not need to implement graceful shutdown routines, then you can use closesocket and it will send the other machine an FD_CLOSE. Although this is not the microsoft recommended way of initiating a shutdown because it is a "forceful" shutdown. The method you implement is completely up to you.

NB: In the graceful shutdown method, if you receive an FD_CLOSE message, you can still SEND data to the client who initiated the shutdown, but the client has told the server it won't send any more data so the Server doesn't need to initiate a receive. You don't have use this method if the client won't need anything after it closes the connection.

NB: closesocket() sends an FD_CLOSE AND closes the socket so it won't send/receive anymore data! shutdown() sends an FD_CLOSE but DOESN'T close the socket, so you can still RECEIVE data on it. After calling shutdown() you CANNOT SEND anymore data!

From the MSDN article: Graceful shutdown, linger options and socket closure

Client Side
(1) Invoke shutdown(s, SD_SEND) to signal end of session and that client has no more data to send.
_____________Server Side
_____________(2) Receive FD_CLOSE, indicating graceful shutdown in progress and that all data has been received.
_____________(3) Send any remaining response data.
_____________(4) Invoke shutdown(s, SD_SEND) to indicate server has no more data to send.
_____________(4') Invoke closesocket
(5') Get FD_READ and invoke recv to get any response data sent by server
(5) Receive FD_CLOSE indication
(6) Invoke closesocket

Note The timing sequence is maintained from step (1) to step (6) between the client and the server, except for step (4') and (5') which only has local timing significance in the sense that step (5) follows step (5') on the client side while step (4') follows step (4) on the server side, with no timing relationship with the remote party.
Posted on 2002-12-06 01:03:31 by SubEvil
Actually when I call recv during processing FD_CLOSE
it immediatly return 0 even if the socket is non-blocking, as
it's supposed to be , I assume it's an ACK to my FIN when I called shutdown(SB_SEND), and when then I call closesocket() I send final FIN.
What MSDN article you were referring to?

BTW , there is an example of IOCP socket programming in PSDK.
Posted on 2002-12-06 18:33:27 by Sergo
I don't think I made myself clear, you are RIGHT, you WON'T recv() ANYTHING in FD_CLOSE, you should take the recv() out of FD_CLOSE you cannot use it there !!!
FD_CLOSE indicates that the other machine will NOT send anymore data, so you don't need to call recv()!

However, if you initiated a graceful shutdown using shutdown API, you can still send() in FD_CLOSE!

So, do not use recv() in FD_CLOSE message, it's pointless! You can only use send() in FD_CLOSE message if you used shutdown() not closesocket()!
If FD_CLOSE message was sent using closesocket, then you cannot use send() in FD_CLOSE message!!!

To make it more clear ... look on the server side of my last post ...
_____________Server Side
_____________(2) Receive FD_CLOSE, indicating graceful shutdown in progress and that all data has been received.
_____________(3) Send any remaining response data.
_____________(4) Invoke shutdown(s, SD_SEND) to indicate server has no more data to send.
_____________(4') Invoke closesocket
Once the server gets FD_CLOSE ... it doesn't/cannot receive anymore data from the client!

MSDN Article = Graceful shutdown, linger options and socket closure

BTW, have you looked at the example of IOCP in PSDK ... it's so complicated! I would love some simple examples in ASM :(
Posted on 2002-12-09 00:19:33 by SubEvil