11

I want to be able to call recv() without having to block, so I want to make it non-blocking, but I do not want it to be non blocking when sending data. So can a socket be made non-blocking only for the recv() function, or does the blocking/non-blocking mode affects all of the socket functions?

alk
  • 69,737
  • 10
  • 105
  • 255
  • 1
    You can use the `MSG_PEEK` flag to see if there's anything to receive. Or use e.g. `select` with a zero timeout. However, for TCP sockets these methods only work to tell you there is at leas *one* byte to be received, you don't know how much is really available. – Some programmer dude Feb 20 '15 at 19:03
  • 2
    Yes but last I checked recv() won't block if there's even 1 byte of data. – Joshua Feb 20 '15 at 19:16
  • 2
    @Joachim Pileborg But even if I used `MSG_PEEK`, `recv()` would still block. –  Feb 20 '15 at 21:48

2 Answers2

5

For windows, you can use ioctlsocket() to set the socket in non-blocking mode. Unfortunately these settings apply to all operations on the socket. So for your case you'll have to switch it between the receivings and the sendings.

For the records: For linux, you could have used the MSG_DONTWAIT flag in the recv() call arguments. The single call will then be non blocking.

elixenide
  • 44,308
  • 16
  • 74
  • 100
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • 2
    Which is not portable as it's not a standard flag. It's not available in the Windows winsock library for example. – Some programmer dude Feb 20 '15 at 19:19
  • @JoachimPileborg Yes ! My fault: I didn't notice the windows tag. I've edited my answer. – Christophe Feb 20 '15 at 20:11
  • Can't I just do this: `unsigned long l; ioctlsocket(s, FIONREAD, &l);` to see if there is data to be read? –  Feb 20 '15 at 20:27
  • You could do this to see if data is there and switch back (attention: read the remarks on the MSDN link about the switch back to blocking). But perhap's could you also remain in non-blocking mode and only switch back if send() would return error WSAEWOULDBLOCK ? – Christophe Feb 20 '15 at 20:42
  • So `ioctlsocket(s, FIONREAD, &l);` set the socket in non-blocking mode also! Look, what I want is not seeing how much data is available, but rather just see if data is available to be read. Isn't this supposed to let me see that: `recv(s, buffer, 1024, MSG_PEEK)`? It is not working for me, the `recv()` is still being blocked. –  Feb 20 '15 at 20:55
  • I just read the documentation. It does not say anything about `FIONREAD` making the socket non-blocking, only `FIONBIO` is used for this purpose. Anyway I think that using `FIONREAD` is a bad idea, because it looks like you can't tell when the other end has disconnected! –  Feb 20 '15 at 21:46
  • @mahmoud_t1 I see above you wrote FIONREAD and I aknowledged. Sorry FIONBIO of course ! Have you read the tutorial link ? It's the 2 first lines of code in the article – Christophe Feb 20 '15 at 22:05
2

There is no way to make the socket non-blocking just for the recv() function.

However there is something close to that (but flawed), which is by using ioctlsocket() with the FIONREAD flag. For example:

unsigned long l;
ioctlsocket(s, FIONREAD, &l);

This function will return (immediately without blocking) how many bytes is available to be read, although not quite accurate (but we don't care about that, because we are using it to know if there is data to be read and not to know exactly how many bytes are there).

As I have mentioned earlier, this approach is flawed, because it doesn't tell you when the other end has disconnected, because recv() returns 0 on disconnect, and this function will return 0 if no data is available!