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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6326064/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:56:18  来源:igfitidea点击:

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

c++csockets

提问by dustin ledezma

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:

我遇到了调用 recv() 系统调用不会阻塞的问题。我目前有一个客户端 - 服务器结构设置,我遇到的问题是我向服务器发送一条消息,而服务器已设置为如下所示:

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?

它正确接收第一条消息,但 recv() 不会阻止并“接收”垃圾数据,这不是我们想要的。我只想在发送消息时对消息做出反应。任何人都可以建议吗?

回答by Duck

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.

recv() 在完整请求完成之前不一定会阻塞,但可以返回部分请求。返回码将通知您实际收到的字节数可能少于您请求的字节数。即使您指定了 MSG_WAITALL 标志,由于信号等原因,它也可以返回较少的值。

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.

在 posix 系统上,在阻塞模式下 recv 只会阻塞直到存在要读取的数据。然后它将返回该数据,该数据可能少于请求的数量,最多为请求的数量。在非阻塞模式下,如果要读取的数据字节为零,则 recv 将立即返回并返回 -1,将 errno 设置为 EAGAIN 或 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).

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

I can't speak to windows behavior.

我无法谈论 Windows 行为。

回答by Adam Rosenfield

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:

有两种可能性:要么发生错误,要么套接字设置为非阻塞模式。要查看是否发生错误,请检查 的返回值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_NONBLOCKflag:

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

Note that unless you're explicitly changing the blocking behavior, the socket should be blocking by default, so most likely an error is occurring.

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

回答by ultifinitus

If you're on windows, run wsagetlasterror() function and look at the return value.

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

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

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

If you're on a posix compliant system look at errno

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

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

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