c- recvfrom 错误 22

c- recvfrom error 22

好的,首先是代码:

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].

中仍然有接收到的值

运行 这在我的 VM 和 xubuntu 中运行良好。

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

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

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

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

cli_len = sizeof(cli_addr);

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

你必须告诉 recvfrom() cli_addr 实际上有多大。 documentation:

中明确说明了这一点

The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.

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

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

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

雷米的回答也很相关,但不是问题的解决方案。如果 cli_len 太小,事先不设置只会导致 sockaddr 被截断。没有为此生成错误。