Trevor Trevor - 3 months ago 18
C Question

How to exit a blocking recv() in Windows?

I have a thread that contains a blocking

recv()
call, something like this:

{
while(1)
{
recv(socket, buffer, sizeof(buffer), 0);
}
}


Now what I want to do is to signal the
recv()
function from another thread to make it exit its blocking state. I have read the following answer from another question that talks about how to do this in Unix (How to let a thread which blocks on recv() exit gracefully?):


Either:


  1. Set a read timeout, with
    setsockopt()
    and
    SO_RCVTIMEO
    , and whenever it triggers check a state variable to see if you've told
    yourself to stop reading.

  2. If you want to stop reading the socket forever, shut it down for input with
    shutdown(sd, SHUT_RD)
    . This will cause
    recv()
    to return
    zero from now on.

  3. Set the socket into non-blocking mode and use
    select()
    with a timeout to tell you when to read, adopting the same strategy with a
    state variable as at (1) above. However non-blocking mode introduces
    considerable complications into the send operation, so you should
    prefer (1) or (2) above.



Your pseudo-code lacks EOS- and error-checking. I hope it doesn't
really look like that.


I am not interested in the first and third solutions because the CPU will probably get exhausted, and based on my testing, the second solution is not supported in Windows (am I right?). So is there another solution to exit a blocking
recv()
?

Answer

A blocking recv() exits only if:

  1. data is read.

  2. The read times out (SO_RCVTIMEO).

  3. The connection is closed.

If none of those options are viable for you, you will have to simply not call recv() in blocking mode until you know there is something waiting to be read, as reported by select(), WSAAsyncSelect(), or WSAEventSelect().

Otherwise, re-write your socket logic to either:

  1. use the socket in non-blocking mode.

  2. use WSARecv() or RIOReceive/Ex() with Overlapped I/O or an I/O Completion Port. An I/O operation can be canceled with CancelIo/Ex().