我尝试按顺序读取UDP数据。但在第二次阅读操作期间遇到问题。您可以在下面的snippest中看到我第一次尝试读取并从UDP接收缓冲区中丢失了12个字节的数据包。
Snippest Code:
sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
bytesInBuffer = 0;
if (-1 == ioctl(sock, FIONREAD, &bytesInBuffer))
{
printf("%s:%d, Fail to read bytes in buffer\n", __func__, __LINE__);
//If failure on ioctl then continue with select and read functionality
bytesInBuffer = 0;
}
printf("%s:%d, bytesInBuffer: %d\n", __func__, __LINE__, bytesInBuffer);
errno = 0;
/* Now recv as it will not block */
i32RetVal = recvfrom(sock, buffer, 40, MSG_NOSIGNAL | MSG_DONTWAIT, NULL, NULL);
printf("%s:%d, i32RetVal: %d\n", __func__, __LINE__, i32RetVal);
if (0 > i32RetVal)
{
printf("%s:%d, Recv failed with status: %d, Err: %d, SErr: %s\n", __func__, __LINE__, status, errno, strerror(errno));
status = -1;
break;
}
else if (0 == i32RetVal)
{
/* other side closed its send pipe */
status = -1;
printf("%s:%d, Recv failed as other side closed pipe\n", __func__, __LINE__);
break;
}
bytesInBuffer = 0;
if (-1 == ioctl(sock, FIONREAD, &bytesInBuffer))
{
printf("%s:%d, Fail to read bytes in buffer\n", __func__, __LINE__);
//If failure on ioctl then continue with select and read functionality
bytesInBuffer = 0;
}
printf("%s:%d, bytesInBuffer: %d\n", __func__, __LINE__, bytesInBuffer);
Output:
Recv_from:304, bytesInBuffer: 52
Recv_from:309, i32RetVal: 40
Recv_from:332, bytesInBuffer: 0
问题: 为什么读取缓冲区的12个字节被丢弃了?
任何帮助将不胜感激。 :)
答案 0 :(得分:3)
如果您阅读the UDP(7)
manual page,您会看到FIONBIO
的此条目:
...以整数形式返回 下一个待处理数据报 的大小(以字节为单位),或者当没有数据报待处理时返回0。 ...
(强调我的。)
因此FIONBIO
没有给出缓冲区中的字节数,而是下一个数据包的大小。如果没有收到新的数据包,你就会得到零。
答案 1 :(得分:3)
您的代码的作用是:
recvfrom
是否返回0,MSG_DONTWAIT
标志< / LI>
值得注意的是,UDP在严格的每个数据报的基础上工作。你不能阅读半个数据报(好吧,你可以......但......继续阅读)。
无论发生什么情况,您都会收到完整的数据报或什么都没有。数据报可能会丢失(将丢失),但不会丢失。您将也始终读取完整的数据报(“阅读”,如“消费”)。
读取数据报会将其从发送缓冲区中删除。读取半个数据报(或其任何部分)将其从发送缓冲区中删除,丢弃其余部分。
答案 2 :(得分:1)
缓冲区保存数据报,而不仅仅是有效负载数据。