如何知道我是否从非阻塞套接字读取了所有内容

Via*_*dko 0 c sockets

我有一个我接受的非阻塞连接套接字:

我有一个非阻塞套接字连接,在收到数据包后,我尝试使用 recv 读取更多数据。

struct sockaddr accepted_address;
socklen_t accepted_address_size = sizeof(accepted_address);

int fd = accept(server_fd, &accepted_address, &accepted_address_size);
make_nonblocking(fd);

... // wait when socket is ready to give me data

char buffer[BUF_SIZE];
int  used = 0;

while (true) {
    int bytes_received = recv(fd, buffer, BUF_SIZE, 0);
    if (bytes_received > 0) { /* OK */ }
    else if (bytes_received < 0) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            /* Should wait for more data, BUT I WILL WAIT INDEFINITELY!!! */
        } else {
            /* Handle error */
        }
    } else {
        /* EOF, OK, Process received data */
    }
}
Run Code Online (Sandbox Code Playgroud)

errno == EAGAIN当第一个 recv 调用检索整个消息,但后续调用导致,导致无限期等待更多永远不会到达的数据时,就会出现问题。

根据这个答案, 这种行为是预期的。

我的问题是: 如果第二次调用 recv 不会给我 EOF 而是返回 EAGAIN,让我无限期地等待,我如何可靠地确定我已收到整个消息?

Ste*_*ich 6

我如何可靠地确定我已收到完整的消息......

TCP没有消息的概念,它只是一个字节流。这意味着要确定消息的结尾,您需要首先根据您正在实现的应用程序协议了解消息是什么,例如以 结尾的行\n、固定大小的消息或以其大小为前缀的某些有效负载。基于此,您可以检查到目前为止收到的数据是否仅代表消息的一部分、完整消息,甚至不止一条消息。

  • 无论您使用阻塞还是非阻塞套接字,此要求都适用。 (3认同)