【问题标题】:c- recvfrom error 22c-recvfrom 错误 22
【发布时间】:2015-10-03 11:06:51
【问题描述】:

好的,首先是代码:

int recvMast_sock;
struct sockaddr_in serv_addr, cli_addr;
socklen_t cli_len;
if ((recvMast_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  {
    critErr("listen:socket=");
  }

fillSockaddrAny(&serv_addr, UDP_NODE_LISTEN_PORT);// fills the sockaddr_in works fine elsewhere

if ((bind(recvMast_sock, (struct sockaddr*) &serv_addr, sizeof serv_addr)) < 0)
  {
    critErr("listen:bind recv_mast_sock:");
  }
recvReturn_i = recvfrom(recvMast_sock, &recvBuff[0], (size_t)1, 0, (struct   sockaddr*) &cli_addr, &cli_len);
if(recvReturn_i <0)
        printf("recv error%d\n",errno);

critErr 是一个处理错误的函数,其中还包括错误的打印和exit

如果有任何相关性,这将在一个线程中运行。如果我在具有 ARM Cortex A9 和 Linaro Linux(基于精确的 Ubuntu)的 Zedboard(ZYNQ-7000 SoC)上编译并运行它。它打印错误22,但在recvBuff[0] 中仍有接收到的值。

使用 xubuntu 在我的虚拟机中运行它可以正常工作。

错误22 等于EINVAL,这被描述为无效参数。

recvfrom(2) 的联机帮助页中,它声明EINVAL 表示设置了MSG_OOB 标志,但我没有使用任何标志(通过0)。

在星期五离开之前,我开始了apt-get 升级,因为我希望它是一个有问题的库或类似的东西。我可以在星期一回来查看,但也许这里有人有另一个想法是什么问题。

【问题讨论】:

  • 我非常怀疑这与架构有关,而是检查设置是否正常。
  • 设置在什么意义上。是安装linux还是硬件?除此以外,网络工作正常。这不是第一次调用 recvfrom。
  • 两者都可能,但我会先检查 linux 安装。他们都是同一个Ubuntu吗?
  • 如前所述,VM 运行 xubuntu (15.04),另一个是 linaro(基于精确 Ubuntu)
  • 这似乎是一个旧的,我不是 Ubuntu 的粉丝,但从我的记忆中精确是旧的。某些库函数中可能确实存在错误。尝试在虚拟机上安装 linaro 并检查它是否仍然重现问题,如果没有,您可以 也许 归咎于架构,但我不明白这是怎么回事特定问题可能与此有关。

标签: c linux sockets linaro


【解决方案1】:

您需要先初始化cli_len,然后再将其传递给recvfrom()

cli_len = sizeof(cli_addr);

你没有初始化它,所以它有一个随机值。如果该值恰好是 sizeof(cli_addr),recvfrom() 可能会因EINVAL 而失败,或者至少截断地址,因为它认为cli_addr 不足以接收客户端地址。如果该值远大于sizeof(cli_addr)recvfrom() 可能会认为缓冲区超出了有效内存范围。

你必须告诉recvfrom() cli_addr 实际上有多大。这在documentation中有明确说明:

参数 addrlen 是一个值-结果参数,调用者应该在调用之前将其初始化为与 src_addr 关联的缓冲区的大小,并在返回时修改以指示源地址的实际大小。如果提供的缓冲区太小,返回的地址会被截断;在这种情况下,addrlen 将返回一个大于提供给调用的值。

所以你必须在调用recvfrom()之前用cli_addr的总大小初始化cli_len,然后recvfrom()用实际写入cli_addr的地址的大小更新cli_lencli_addr 可以大于地址,例如,当使用sockaddr_storage 结构在双栈套接字上接受 IPv4 或 IPv6 地址时。在问题的示例中,正在使用 IPv4 套接字,因此必须将 cli_len 初始化为值 >= sizeof(sockaddr_in)

【讨论】:

    【解决方案2】:

    这不是由操作系统或架构引起的。由于互斥锁阻塞,该函数未在 x86 系统上调用。所以我没有在那里得到错误。

    问题是我将套接字从'main'传递给了这个函数(我没有在问题中说明,因为我认为这无关紧要,我的错......) 在'main'中,我使用它并在这个函数中使用它。虽然是互斥的,但还是有这个错误。

    雷米的回答也很相关,但不是解决问题的方法。如果 cli_len 太小,则不预先设置只会导致削减 sockaddr。没有产生任何错误。

    【讨论】:

      猜你喜欢
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      • 2013-11-16
      • 1970-01-01
      相关资源
      最近更新 更多