c - 奇怪的UDP丢包

标签 c linux sockets udp recv

我尝试顺序读取 UDP 数据报。但在第二次读取操作期间出现问题。您可以在下面的代码片段中看到我第一次尝试读取并从 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 个字节被丢弃?

任何帮助将不胜感激。 :)

最佳答案

你的代码是这样的:

  • 查询接收缓冲区中下一个数据报的大小,为52字节
  • 从接收缓冲区中的下一个数据报中读取 40 个字节并丢弃其余部分
  • 检查 recvfrom 是否返回 0,这永远不会是这种情况,因为套接字未设置为非阻塞 -- 我的错,忽略了 MSG_DONTWAIT 标志
  • 错误地假设零长度接收意味着“另一端已关闭连接”——这是针对 TCP 的。 UDP 没有连接或“管道”,没有什么可以关闭:零长度意味着“无有效载荷”数据报,它仅包含 header (这是完全合法的!)
  • 查询接收缓冲区中下一个数据报的大小(为零,因为没有)

值得注意的是,UDP 在严格的每个数据报基础上工作。您无法读取半个数据报(好吧,您可以……但是……请继续阅读)。

无论发生什么,您总是会收到一个完整的数据报或什么也没有。数据报可能会丢失( 丢失),但字节不会。您将始终读取完整的数据报(“读取”与“消费”一样)。

读取数据报会将其从发送缓冲区中移除。读取半个数据报(或其任何部分)会将其从发送缓冲区中删除,丢弃其余部分

关于c - 奇怪的UDP丢包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27229516/

相关文章:

c - Mac .dylib 链接找不到 header

c - 函数从链表中删除第 n 个位置的节点,给出段错误

linux - qemu makefile错误找不到我知道的库

c - C 中的 "thread fork"(理想情况下是 POSIX,但仅适用于 Linux)

c++ - 寻找API来衡量流程的电池使用情况

silverlight - 如何找出我应该从套接字读取多少?

c - 如何为每个元音创建一个流程?

C 在 stdin 中检测用户输入的字符

c++ - 在 C++ 程序运行时加载文件

安卓(原生): why my socket isn't available to other processes?