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

时间:2015-07-22 13:01:16

标签: c sockets embedded-linux

我试图读取从网络接收的前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个字节。 任何想法?

2 个答案:

答案 0 :(得分:3)

recv()函数不保证读取指定的完整字节数。它的Linux手册页以这种方式描述:

  

接收电话通常会返回任何可用的数据,最多可达到所要求的金额,而非等待收到所需的全部金额。

这样就像read(2),我更喜欢大多数用途。套接字的类型(流与数据报)会对此产生影响,但无论使用哪种函数,您都可能需要准备循环,重复读取以收集消息的所有部分。

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

答案 1 :(得分:0)

您需要连续检查recv的返回值,以找出每次recv调用收到的字节数。原因是您正在使用流协议,您可以随时接收任意数量的字节,而不是您在发送方发送的方式。

如果您发送100个字节,然后立即再次发送100个字节,则可能会收到200个字节,但也可能是150和50或其他内容。您的逻辑应该这样编写,以便数据流可以被切割成许多任意大小的片段。所以你需要一种一直调用receive的循环并填充一些中间缓冲区。只有当你收到4个字节时,你才能知道还有多少字节,但你不知道需要多少个recv调用。此外,如果您发送多种这样的消息。长度后跟长度字节数据,然后再长度跟随数据(2条消息)。请注意,您将以连续流的形式收到此消息,以便您可以接收上一个数据包的数据以及下一个数据包的长度以及下一条消息的一些字节。你需要相当多的逻辑来应对这种情况,因为长度本身的4个字节可以被打破并分散在2个或更多的recv调用上。

同时检查是否接收到0个字节,因为这意味着对等体已关闭其连接结束。

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