Reputation: 635
I'm having a problem where calling recv() system call does not block. I have a client-server structure setup at the moment, and the problem I am having is I send the server one message, while the server is set up so that it's something like:
while (1) {
char buf[1024];
recv(fd, buf, sizeof(buf), flags);
processMsg(buf);
}
It receives the first message correctly, but the recv() does not block and "receives" trash data which is not what is desired. I'd like to react to messages only when they are sent. Can anyone advise?
Upvotes: 13
Views: 87950
Reputation: 27542
recv() does not necessarily block until the full request is fulfilled but can return a partial request. The return code will inform you of how many bytes were actually received which can be less than you requested. Even if you specify a MSG_WAITALL flag it can return less due to a signal, etc.
On posix systems, in blocking mode recv will only block until some data is present to be read. It will then return that data, which may be less than requested, up to the amount requested. In non-blocking mode recv will return immediately if there is zero bytes of data to be read and will return -1, setting errno to EAGAIN or EWOULDBLOCK.
The upshot is that normally you will call recv in a loop until you get the amount you want while also checking for return codes of 0 (other side disconnected) or -1 (some error).
I can't speak to windows behavior.
Upvotes: 22
Reputation: 400146
There's two possibilities: either an error is occurring, or the socket is set to non-blocking mode. To see if an error is occurring, check the return value of recv
:
while() {
char buf[1024];
int ret = recv(,buf,,)
if(ret < 0) {
// handle error
printf("recv error: %s\n", strerror(errno));
} else {
// only use the first ret bytes of buf
processMsg(buf, ret);
}
}
To put the socket into non-blocking mode, or to query if a socket is in non-blocking mode, use fcntl(2)
with the O_NONBLOCK
flag:
// Test if the socket is in non-blocking mode:
if(fcntl(sockfd, F_GETFL) & O_NONBLOCK) {
// socket is non-blocking
}
// Put the socket in non-blocking mode:
if(fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK) < 0) {
// handle error
}
Note that unless you're explicitly changing the blocking behavior, the socket should be blocking by default, so most likely an error is occurring.
Upvotes: 18
Reputation: 1883
If you're on windows, run wsagetlasterror() function and look at the return value.
http://msdn.microsoft.com/en-us/library/ms741580%28v=vs.85%29.aspx
If you're on a posix compliant system look at errno
http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html
Upvotes: 1