繁体   English   中英

C/C++ sockets 和非阻塞 recv()

[英]C/C++ sockets and a non-blocking recv()

我遇到了调用 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);
    }
}

要将套接字置于非阻塞模式,或查询套接字是否处于非阻塞模式,请使用带有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
}

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

如果您使用的是 windows,请运行 wsagetlasterror() function 并查看返回值。

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

如果您使用的是 posix 兼容系统,请查看 errno

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM