Link to home
Start Free TrialLog in
Avatar of chsalvia
chsalvia

asked on

Recv timeout on non-blocking socket

I'm trying to figure out how to avoid recv() calls that hang forever by using using a non-blocking socket along with the select() function.  This seems to be the standard way to avoid recv() calls that hang forever.

I'm having difficulty getting this to work however.  It seems to work sometimes, but occasionally the recv() call hangs.  Additionally, I think the loop I'm using is not doing something right, because it slows down the system indicating it is using a lot of CPU cycles.

Here is the recv() function I used:

      bool recv_non_block(char* buf)
      {      
            int status;
            do {
                  if ((status = recv(m_sock, buf, RECV_BUF_SIZE, 0)) == -1) {
                        if (errno == EWOULDBLOCK || errno == EAGAIN) {
                              if (Select()) continue;
                        }
                        else return false;
                  }
            } while (status != 0);
            return true;
      }

Note: The Select() function is simply a convenient wrapper for the select() function call.

Is the above loop a correct way to receive on a non-blocking socket?  Note also that since this can be used on an Internet website, I do not necessarily know the size of the data I am receiving, and therefore I need to rely on recv() returning 0 in order to end the loop.
Avatar of ethan_mmg
ethan_mmg

Why not use recv in its own thread? It can block there while waiting for input. When data arrives, it can send a message to your main thread.
Avatar of chsalvia

ASKER

That's one possible solution.  But in a multi-threaded environment that would require twice as many threads.

I have discovered that creating a truly robust recv timeout is actually one of the most difficult things to program.  Every approach I try has some flaw in it.  For example, I initially tried using blocking sockets, and setting the SO_RCVTIMEO property.  This seemed to work well, but when I used a lot of concurrent threads, various recv calls would still mysteriously hang.  

Another option was to simply use SIGALRM to time out.  But this doesn't work well in a multi-threaded environment either.

So finally I tried non-blocking sockets.  This way I have more control over the recv() call.  Again, this seems to work fine initially.  But when there are a lot of concurrent threads, many of them still hang on recv().
ASKER CERTIFIED SOLUTION
Avatar of Computer101
Computer101
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial