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 被截断。没有为此生成错误。
好的,首先是代码:
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 被截断。没有为此生成错误。