Winsock udp recv即使在循环内也无法接收所有数据

时间:2019-05-29 16:25:13

标签: c++ sockets udp

我有一些利用winsock的UDP接收代码,特别是AF_INET,SOCK_DGRAM和IPPROTO_UDP。 recv调用存在于循环中,该循环读取直到接收到所有数据为止。问题是我每次只会得到部分数据。此外,我什至不需要循环,因为我可以看到所有数据都存在于单个数据包中。在wireshark中,我看到实际数据长度为299字节。 Wireshark成功查看了整个数据包,因此我知道数据包发送方工作正常。

使用我的Windows UDP代码,我只能得到8个字节,直到我的receive方法返回为止。我可以看到UDP代码在看到00字节时正在停止。 Wireshark可以读取过去的00个字节,但Windows udp recv无法读取过去的00个字节。 Windows似乎以00结尾,因此得出的结论是该数据包只有8个字节。

我看了wireshark中的标头,发现指定的长度是正确的,所以我对为什么只读取8个字节感到非常困惑。谢谢您的提前帮助。

这是我的接听电话,供参考:

int ret = recv(socket, buffer, 1500, 0);

ret变为8,分配给1500个字节的缓冲区仅填充8个字节

1 个答案:

答案 0 :(得分:0)

UDP是面向消息的,而不像TCP那样面向流。

在UDP中,如果出现以下任一情况,则recv()返回8个字节的 only 方式是:

  • 您将len参数设置为> 8,并且会接收到一个数据报,该数据报恰好包含8个字节。

  • 您将len参数设置为== 8,并接收到包含8个以上字节的数据报。

假设您将len设置为1500,那么唯一的可能性就是接收到的数据报中只有8个字节,而不是您声称的299个字节。

与TCP不同,在UDP中,您不能分段读取数据报,而读取则是一项全有或全无的操作(除非您窥视未执行的数据)。在UDP中,recv() / recvfrom()一次读取整个数据报,如果提供的缓冲区太小而无法接收数据(在这种情况下不是),则发生WSAEMSGSIZE错误将被报告,并且数据将被截断,并丢弃缓冲区中不适合的其余数据。

您描述的00空字节对recv() / recvfrom()读取整个数据报的能力没有任何影响。数据报带有有效载荷长度,并且recv() / recvfrom()将读取该有效载荷长度或指定的缓冲区大小,以较小者为准,而与实际有效载荷内容无关。

因此,在您的代码中,recv()可能根本没有收到您期望的数据报。

例如,要完全在UDP中使用recv(),必须首先使用connect() UDP套接字将其与特定的对等IP /端口相关联,从而允许recv()忽略来自其他对等方的入站数据报(并使send()将数据报发送到特定对等方)。也许您正在connect将UDP套接字连接到错误的对等设备,从而读取了用于其他目的的数据报。或者,也许您是connect正在访问正确的对等设备,并且它实际上正在发送您不期望的8字节数据报。

由于您没有提供有关设置的任何上下文信息,因此涉及的对等方,所涉及的协议,Wireshark捕获都什么也没有,实际上,任何人都无法通过任何方式来诊断您的情况肯定。但是,我上面所描述的将解释您所描述的症状。如果您并非如此,则需要编辑问题以提供更多详细信息。