select() 向 Makefile 添加 m32 标志时失败
select() fails when adding m32 flag to Makefile
我有下面的代码,它只是创建了 udp 套接字来监听
到多播组。
我正在 x64 机器上使用带有 -c -g 标志的 gcc 编译它。
将 -m32 标志添加到 Makefile 中的链接和编译阶段时,
select() 调用因 无效参数 .
而失败
在使用和不使用标志进行一些调试之后,我发现
使用标志我得到所有变量的所有相同值,除了:
readfds: 0x80..(重复 31 次)- 使用 -m32 标志
readfds: 0x80..(重复 15 次)- 没有标志
sock.sin_zero: 0x5c, 0xD5, 0xff, 和一些其他带有 -m32 标志的奇怪值
sock.sin_zero: 0x0,0x0,0x20,0x0,0x0 - 没有标志
所有变量读取都在文件循环内完成,就在 FD_SET
之后
我真的不明白为什么它会完全改变(作为 32 位程序
假设 运行 在 64 位机器上就好了),或者为什么 select() returns
在那种情况下参数无效。
有人可以帮忙吗?
#include <stdio.h>
#include <stdlib.h>
#include <linux/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "radio_listener.h"
int main_loop(int argc, char *argv[])
{
int sock_no = 0;
struct sockaddr_in sock;
socklen_t sock_size;
fd_set readfds;
struct ip_mreq mreq_ip;
uint16_t mreq_port = 0;
char buffer[BUFF_SIZE];
struct timeval timeout_value;
if(VALID_ARGC != argc)
{
fprintf(stderr, "usage: %s <mc_address> <udp_port>\n", argv[0]);
exit(EXIT_FAILURE);
}
mreq_port = atoi(argv[2]);
/* Initialize a socket */
sock_no = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_no < 0)
{
perror("socket() failed!");
exit(1);
}
sock.sin_family = AF_INET;
sock.sin_addr.s_addr = htonl(INADDR_ANY);
sock.sin_port = htons(mreq_port);
sock_size = sizeof(sock);
bind(sock_no, (struct sockaddr *)&sock, sizeof(sock));
/* Initialize the Multicast request */
mreq_ip.imr_multiaddr.s_addr = inet_addr(argv[1]);
mreq_ip.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(sock_no, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq_ip, sizeof(mreq_ip));
while (1)
{
timeout_value.tv_sec = TIMEOUT_VAL;
FD_ZERO(&readfds);
FD_SET(sock_no, &readfds);
int retval = select(sock_no+1, &readfds, NULL, NULL, &timeout_value);
if(-1 == retval)
{
perror("select() failed!");
close(sock);
exit(1);
}
if(0 == retval)
{
printf("Timeout - Closing socket and exiting\n");
break;
}
if(recvfrom(sock_no, buffer, BUFF_SIZE, 0, (struct sockaddr *)&sock, &sock_size) < 0)
{
perror("recvfrom() failed!");
close(sock);
exit(1);
}
printf("%s", buffer);
}
close(sock);
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
int rc = 0;
rc = main_loop(argc, argv);
return rc;
}
编辑
您是否确定了 fd 的最大数量?
一般来说,确定最大数量,然后将其传递给select:
int maxfd;
for (i = 0, maxfd = 0; i < nclients; i++)
{
FD_SET(sock[i], &read_fds);
if (sock[i] > maxfd)
maxfd = sock[i];
}
select(maxfd + 1, ........);
如果您还没有确定 maxfd 是什么,那么它可能会有问题。
( 来自 discussion here )
您没有设置超时参数的 tv_usec
字段,因此它将包含一些垃圾(无论碰巧在分配 timeout_value
的堆栈上)。如果那个随机垃圾恰好是一个负数,你会得到 EINVAL
invalid argument 错误。如果碰巧没问题,你就不会。对事物的微小改变(比如使用 -m32
或不使用)往往会改变这一点。
我有下面的代码,它只是创建了 udp 套接字来监听 到多播组。
我正在 x64 机器上使用带有 -c -g 标志的 gcc 编译它。 将 -m32 标志添加到 Makefile 中的链接和编译阶段时, select() 调用因 无效参数 .
而失败在使用和不使用标志进行一些调试之后,我发现 使用标志我得到所有变量的所有相同值,除了:
readfds: 0x80..(重复 31 次)- 使用 -m32 标志
readfds: 0x80..(重复 15 次)- 没有标志
sock.sin_zero: 0x5c, 0xD5, 0xff, 和一些其他带有 -m32 标志的奇怪值
sock.sin_zero: 0x0,0x0,0x20,0x0,0x0 - 没有标志
所有变量读取都在文件循环内完成,就在 FD_SET
之后我真的不明白为什么它会完全改变(作为 32 位程序 假设 运行 在 64 位机器上就好了),或者为什么 select() returns 在那种情况下参数无效。
有人可以帮忙吗?
#include <stdio.h>
#include <stdlib.h>
#include <linux/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "radio_listener.h"
int main_loop(int argc, char *argv[])
{
int sock_no = 0;
struct sockaddr_in sock;
socklen_t sock_size;
fd_set readfds;
struct ip_mreq mreq_ip;
uint16_t mreq_port = 0;
char buffer[BUFF_SIZE];
struct timeval timeout_value;
if(VALID_ARGC != argc)
{
fprintf(stderr, "usage: %s <mc_address> <udp_port>\n", argv[0]);
exit(EXIT_FAILURE);
}
mreq_port = atoi(argv[2]);
/* Initialize a socket */
sock_no = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_no < 0)
{
perror("socket() failed!");
exit(1);
}
sock.sin_family = AF_INET;
sock.sin_addr.s_addr = htonl(INADDR_ANY);
sock.sin_port = htons(mreq_port);
sock_size = sizeof(sock);
bind(sock_no, (struct sockaddr *)&sock, sizeof(sock));
/* Initialize the Multicast request */
mreq_ip.imr_multiaddr.s_addr = inet_addr(argv[1]);
mreq_ip.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(sock_no, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq_ip, sizeof(mreq_ip));
while (1)
{
timeout_value.tv_sec = TIMEOUT_VAL;
FD_ZERO(&readfds);
FD_SET(sock_no, &readfds);
int retval = select(sock_no+1, &readfds, NULL, NULL, &timeout_value);
if(-1 == retval)
{
perror("select() failed!");
close(sock);
exit(1);
}
if(0 == retval)
{
printf("Timeout - Closing socket and exiting\n");
break;
}
if(recvfrom(sock_no, buffer, BUFF_SIZE, 0, (struct sockaddr *)&sock, &sock_size) < 0)
{
perror("recvfrom() failed!");
close(sock);
exit(1);
}
printf("%s", buffer);
}
close(sock);
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
int rc = 0;
rc = main_loop(argc, argv);
return rc;
}
编辑
您是否确定了 fd 的最大数量?
一般来说,确定最大数量,然后将其传递给select:
int maxfd;
for (i = 0, maxfd = 0; i < nclients; i++)
{
FD_SET(sock[i], &read_fds);
if (sock[i] > maxfd)
maxfd = sock[i];
}
select(maxfd + 1, ........);
如果您还没有确定 maxfd 是什么,那么它可能会有问题。
( 来自 discussion here )
您没有设置超时参数的 tv_usec
字段,因此它将包含一些垃圾(无论碰巧在分配 timeout_value
的堆栈上)。如果那个随机垃圾恰好是一个负数,你会得到 EINVAL
invalid argument 错误。如果碰巧没问题,你就不会。对事物的微小改变(比如使用 -m32
或不使用)往往会改变这一点。