我遇到了一个问题,即调用recv()系统调用不会阻塞。目前我正在设置一个客户端-服务器结构,我遇到的问题是我发送了一条消息给服务器,而服务器则是这样设置的:
while (1) {
char buf[1024];
recv(fd, buf, sizeof(buf), flags);
processMsg(buf);
}
它可以正确地接收第一条消息,但是recv()不会阻塞并"接收"垃圾数据,这不是想要的结果。我希望只在发送消息时才对其进行反应。有人能给予建议吗?
recv()不一定会在完整请求被满足之前阻塞,但可能会返回部分请求。 返回代码将通知您实际接收到的字节数,这可能少于您请求的字节数。 即使您指定了MSG_WAITALL标志,由于信号等原因它也可以返回较少数量的数据。
在posix系统上,在阻塞模式下,recv仅会阻塞直到有一些数据可供读取。 然后它将返回该数据,该数据可能小于所请求的数据,最多达到请求的数量。 在非阻塞模式下,如果没有字节数据可供读取,则recv将立即返回并返回-1,将errno设置为EAGAIN或EWOULDBLOCK。
总之,通常情况下,您会调用recv循环直到获得所需的数量,同时还会检查返回码是否为0(另一方已断开连接)或-1(某些错误)。
我不能确定Windows的行为。
有两种可能性:一是发生了错误,二是套接字被设置为非阻塞模式。要查看是否发生错误,请检查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);
}
}
要将套接字设置为非阻塞模式,或查询套接字是否处于非阻塞模式,请使用fcntl(2)
函数并传入O_NONBLOCK
标志:
// 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
}
请注意,除非您明确更改了阻止行为,否则套接字应默认为阻止状态,因此很可能会发生错误。
http://msdn.microsoft.com/en-us/library/ms741580%28v=vs.85%29.aspx
如果您正在使用符合posix标准的系统,请查看errno。http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html
recv
返回-1,否则它们都没有意义。 - Ben Voigt
recv
的返回代码。否则当你愉快地查看缓冲区中的某些垃圾时,它可能会因错误而大声尖叫。 - user405725