在 C 套接字中调用 recv 两次时丢失接收到的数据

Lost recieved data when calling recv twice in C socket

我正在尝试读取从网络接收到的前 4 个字节以获得整个消息长度,然后我得到的所有消息都是这样的:

#include <sys/socket.h>
int len,length;
char *buffer, lengthX[4];
recv(com_handle, lengthX, 4, 0);
sscanf(lengthX, "%" S(4) "X", &len);
length=recv(com_handle, buffer , len, 0);

出于某些原因,我丢失了消息其余部分的 13 个字节。 有什么想法吗?

recv() 函数不保证读取指定的全部字节数。它的 Linux 手册页是这样描述的:

The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.

这种方式类似于 read(2),我更喜欢这种方式用于大多数用途。套接字的类型(流与数据报)对此有影响,但无论使用哪种功能,您都可能需要准备好循环,反复读取以收集所有消息片段。

并且总是检查系统调用的return值。在这种情况下,您不仅需要这样做来检测错误,还需要这样做以确保您完全正确阅读。

您需要不断检查 recv 的 return 值,以了解每次 recv 调用收到了多少字节。原因是您使用的是流式传输协议,您可以随时接收任意数量的字节,而不是以您在发送方发送它们的方式。

如果您发送 100 个字节,然后立即再次发送 100 个字节,您很可能会收到 200 个字节,但也可能是 150 和 50 或其他。你的逻辑应该这样写,数据流可能被分成许多任意大小的片段。所以你需要一个一直调用接收并填充一些中间缓冲区的某种循环。只有当您收到 4 个字节时,您才能知道还有多少字节尚未到来,但您不知道将进行多少次 recv 调用。此外,如果您发送多条此类消息。长度后跟数据的长度字节,然后又是长度后跟数据(2 条消息)。请注意,您将以连续流的形式接收到它,因此您可能会收到前一个数据包的数据以及下一个数据包的长度以及下一条消息的一些字节。你需要相当多的逻辑来处理这个问题,因为你的 4 个字节的长度本身可以被破坏并分布在 2 个 recv 调用或更多。

还要检查是否接收到 0 字节,因为这意味着对等方已关闭其连接端。

您应该阅读更多关于网络编程的内容 我总是在这里看到同样的错误,人们就是不明白什么是流式传输协议。但是这种信息可以在互联网上找到。先开始阅读,然后是理解,然后是实验和编码,然后是进一步的理解。