Visual C++ Network: When does 'recv()' return?
Q: When does 'recv()' return?
A: In the case of a successful call, 'recv()' returns in only two circumstances. One is in the case of arrival of data, the other is in the case of a graceful closure. 'recv()' returns the number of bytes received in the case of data arrival, or 0 if the connection has been closed gracefully. Now, let us examine 'recv()' in the case of the arrival of data.
As against what is considered by some, 'recv()' does not necessarily return when the data from the corresponding 'send()' arrive (as indicated by the FAQ "Does one call to 'send()' result in one call to 'recv()'?"). Technically, 'recv()' returns in three circumstances:
- The receive buffer is full.
- 500ms has passed since the last arrival of data.
- Data arrives with the PUSH-bit set.
In the first case 'receive buffer' means either the buffer we submit or the intermediate winsock buffer. This depends on whether or not there is data in the intermediate buffer at the time of issuing a 'recv()' call.
At the time of calling, if the data is ready to be delivered from the winsock buffer, the 'recv()' call completes immediately, and in the case of overlapped receiving (using 'WSARecv()') it completes successfully and the completion is posted. On the other hand, if the buffer is empty, 'recv()' blocks (for overlapped receive calls, it will return with the error 'WSA_IO_PENDING') and the buffer that is submitted will be locked. Once the buffer is locked, at the time of data arrival, the data is copied directly into the application buffer - thus bypassing the winsock buffer in the process.
The PUSH-bit need not be set for each send, esp. for continuous ones. But this can be overcome by setting the registry parameter ('IgnorePushBitOnReceives') so that for each packet that arrives at the receiving side, it is treated as if the PUSH-bit is set. This is recommended only if the TCP implementation is not properly pushing the data.
Thanks to Mr. Andreas Masur for his help.