将m32标志添加到Makefile时,select()失败

时间:2015-12-30 20:24:37

标签: c linux select makefile 32bit-64bit

我有以下代码,它只是创建udp套接字来监听 到多播组。

我正在x64机器上使用带有-c -g标志的gcc编译它。 将-m32标志添加到链接&在Makefile中编译阶段, select()调用失败,无效参数

在有和没有旗帜的情况下稍微调试一下后,我发现了这一点 使用标志我得到所有变量的所有相同值,除了:

readfds:0x80 ..(重复31次) - 带-m32标志

readfds:0x80 ..(重复15次) - 没有标志

sock.sin_zero:0x5c,0xD5,0xff以及其他一些奇怪的值WITH -m32 flag

sock.sin_zero:0x0,0x0,0x20,0x0,0x0 - 没有国旗

所有变量读取都在文件循环内完成,紧接在FD_SET

之后

我真的不明白它为什么会改变整体(作为32位程序 假设在64位机器上运行得很好),或者为什么select()返回 无效参数。在这种情况下。

有人可以帮忙吗?

#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;
}

2 个答案:

答案 0 :(得分:4)

您没有设置超时参数的tv_usec字段,因此它将包含一些垃圾(无论发生在堆栈上timeout_value被分配的情况)。如果该随机垃圾恰好是负数,则会出现EINVAL无效参数错误。如果碰巧没问题,你就不会。事情的微小变化(比如使用-m32)会改变这种情况。

答案 1 :(得分:1)

<强> 修改
你确定了fd的最大数量吗?

通常,确定最大数量,然后将其传递给选择:

  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