C / C ++套接字和非阻塞recv()

时间:2011-06-13 02:09:38

标签: c++ c sockets

我遇到一个调用recv()系统调用没有阻塞的问题。我目前有一个客户端 - 服务器结构设置,我遇到的问题是我向服务器发送一条消息,而服务器设置为这样:

while (1) {
   char buf[1024];
   recv(fd, buf, sizeof(buf), flags);
   processMsg(buf);
}

它正确接收第一条消息,但recv()不会阻止和“接收”不符合要求的垃圾数据。我只想在发送邮件时才对邮件作出反应。任何人都可以建议吗?

3 个答案:

答案 0 :(得分:12)

在满足完整请求之前,

recv()不一定会阻塞,但可以返回部分请求。返回代码将通知您实际接收的字节数可能少于您的请求。即使你指定了一个MSG_WAITALL标志,它也可以因信号而返回较少等等。

在posix系统上,在阻塞模式下,recv只会阻塞,直到某些数据存在才能被读取。然后它将返回可能少于请求的数据,直到请求的数量。在非阻塞模式下,如果要读取零字节数据,recv将立即返回,并返回-1,将errno设置为EAGAIN或EWOULDBLOCK。

结果是通常你会在循环中调用recv,直到你得到你想要的数量,同时检查返回代码为0(另一侧断开)或-1(某些错误)。

我无法谈论Windows行为。

答案 1 :(得分:12)

有两种可能:发生错误,或者套接字设置为非阻塞模式。要查看是否发生错误,请检查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);
    }
}

要将套接字置于非阻塞模式,或查询套接字是否处于非阻塞模式,请使用带有O_NONBLOCK标志的fcntl(2)

// 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
}

请注意,除非您明确更改阻止行为,否则默认情况下套接字应该是阻止的,因此很可能发生错误。

答案 2 :(得分:1)

如果您在Windows上,请运行wsagetlasterror()函数并查看返回值。

http://msdn.microsoft.com/en-us/library/ms741580%28v=vs.85%29.aspx

如果您使用符合posix标准的系统,请查看errno

http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html