2

好的,首先是代码:

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)表示设置EINVALMSG_OOB标志,但我不使用任何标志(通过0)。

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

4

2 回答 2

5

您需要cli_len在将其传递给之前进行初始化recvfrom()

cli_len = sizeof(cli_addr);

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

你必须说出实际有recvfrom()多大cli_addr这在文档中明确说明:

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

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

于 2015-10-03T15:37:11.480 回答
0

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

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

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

于 2015-10-06T21:49:45.120 回答