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

我有一个非阻塞套接字连接,在收到一包数据后,我try 使用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 */
    }
}

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

按每this answer 这是意料之中的行为.

我的问题是: How can I reliably determine that I have received the entire message if the second call to recv won't give me EOF but instead returns EAGAIN, leaving me waiting indefinitely?

推荐答案

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

TCP没有消息的概念,它只是一个字节流.这意味着要确定消息的结尾,您需要首先了解消息在应用程序协议方面是什么,例如以\n结尾的行、固定大小的消息或以其大小为前缀的有效负载.在此基础上,您可以判断到目前为止收到的数据是否只表示消息的一部分、完整消息或甚至不止一条消息.

C++相关问答推荐

try 使用sigqueue函数将指向 struct 体的指针数据传递到信号处理程序,使用siginfo_t struct 体从一个进程传递到另一个进程

ISO_C_BINDING,从Fortran调用C

在C语言中使用scanf()时我无法理解的警告

在函数中使用复合文字来初始化C语言中的变量

如何在不使用其他数组或字符串的情况下交换字符串中的两个单词?

如何在C中引发/处理自定义信号?

将uintptr_t添加到指针是否对称?

VS代码';S C/C++扩展称C23真关键字和假关键字未定义

在C++中访问双指针

为什么指针运算会产生错误的结果?

将数组插入数组

C语言中MPI发送接收字符串时出现的分段错误

链接器脚本和C程序使用相同的头文件,这可能吗?

C-try 将整数和 struct 数组存储到二进制文件中

我正在try 将QSORT算法实现为C++中的泛型函数

int * 指向int的哪个字节?

*S=0;正在优化中.可能是GCC 13号虫?或者是一些不明确的行为?

问题:C#Define上的初始值设定项元素不是常量

哪个首选包含第三个库S头文件?#INCLUDE;文件名或#INCLUDE<;文件名&>?

从Raku nativecall调用时精度不同