Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 多接口多播中任意特定接口与INADDR_的套接字绑定_C_Sockets_Networking_Udp_Multicast - Fatal编程技术网

C 多接口多播中任意特定接口与INADDR_的套接字绑定

C 多接口多播中任意特定接口与INADDR_的套接字绑定,c,sockets,networking,udp,multicast,C,Sockets,Networking,Udp,Multicast,我正在尝试编写多播服务器。我有两个问题: 如何在多个接口(如以太网/wifi接口)上发送多播公告。我是否需要为每个接口和绑定创建多个套接字 当使用INADDR_任意地址绑定套接字时,描述符准备好执行I/O操作(使用select调用),但当我使用特定接口地址(如以太网/wifi)绑定时,描述符不准备执行任何操作,它仅停留在select api。 那么,使用默认地址(INADDR_ANY)绑定套接字与使用特定接口地址绑定套接字之间有什么区别呢 int sd = socket(AF_INET, SOC

我正在尝试编写多播服务器。我有两个问题:

  • 如何在多个接口(如以太网/wifi接口)上发送多播公告。我是否需要为每个接口和绑定创建多个套接字

  • 当使用INADDR_任意地址绑定套接字时,描述符准备好执行I/O操作(使用select调用),但当我使用特定接口地址(如以太网/wifi)绑定时,描述符不准备执行任何操作,它仅停留在select api。 那么,使用默认地址(INADDR_ANY)绑定套接字与使用特定接口地址绑定套接字之间有什么区别呢

    int sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sd < 0) {
            printf("scoket() failed");
            return sd;
    }
    
    int r = -1;
    
    int on = 1;
    if ((r = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on))) < 0) {
            printf("recv setsockopt(SO_REUSEADDR) failed");
            return r;
    }
    // add membership to receiving socket
    struct ip_mreq mreq;
    memset(&mreq, 0, sizeof(struct ip_mreq));
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    mreq.imr_multiaddr.s_addr = inet_addr(MDNS_ADDR);
    if ((r = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
            printf("recv setsockopt(IP_ADD_MEM) failed");
            return r;
    }
     // enable loopback in case someone else needs the data
    if ((r = setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &on, sizeof(on))) < 0) {
            printf("recv setsockopt(IP_MULTICAST_LOOP) failed");
            return r;
    }
    
    
    #ifdef IP_PKTINFO
    if ((r = setsockopt(sd, SOL_IP, IP_PKTINFO, (char *) &on, sizeof(on))) < 0) {
            printf("recv setsockopt(IP_PKTINFO) failed");
            return r;
    }
    #endif
    /* bind to an address */
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(MDNS_PORT);
    //serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);       /* receive multicast */
    serveraddr.sin_addr.s_addr = inet_addr("192.168.10.23");        /* receive multicast */
    if ((r = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0) {
            printf("recv bind()");
    }
    

    当套接字id与INADD_绑定时,任何地址select都将返回,并且我可以使用文件描述符读取,但当与特定接口绑定时,select将永不返回,因为没有可读取的文件描述符。

    将套接字与特定地址绑定是将其锁定到设备的通用方法。这种方法有点过时,因为在程序启动后,可以在设备上更改地址。总的来说,我建议绑定到INADDR_ANY

    您可以随时更改套接字上的输出多播设备

    可考虑的备选方案:

    man 7 ip:
    IP_MULTICAST_ALL-传送到所有设备(默认值1)
    IP_MULTICAST_IF-我很确定这只会设置输出设备

    man 7插座:
    因此,我们必须提供设备

    只需在选项上玩一点,看看结果如何

  • 如何在多个接口(如以太网/wifi接口)上发送多播公告。我是否需要为每个接口和绑定创建多个套接字
  • 否。在网络接口上循环,然后依次调用
    setsockopt()
    ,并为每个接口提供适当的连接参数。你只需要一个插座

  • 当将套接字与INADDR_绑定到任意地址时,描述符准备好执行I/O操作(使用select调用)
  • 那是不对的。您的代码只检查可读性

    但当我绑定特定的接口地址(如以太网/wifi)时,描述符无法执行任何操作

    同样,这是不正确的。您只检查可读性,而不是“任何操作”。所有这一切意味着没有多播通过您绑定到的地址进入

    它仅停留在select api上。那么,使用默认地址(INADDR_ANY)绑定套接字与使用特定接口地址绑定套接字之间有什么区别呢


    它确定您通过发送和接收的IP地址。

    当您绑定到
    INADDR\u ANY
    并调用
    select
    时,是否检查
    select
    返回的内容?并检查
    sockfd\u set
    中设置了哪些描述符?说到错误,如果任何系统调用失败,您应该真正打印(可能需要的帮助)。我已将套接字描述符添加到sockfd_集,并且select将在使用INADDR_绑定时返回1,之后我将使用FD_ISSET检查套接字描述符,并对特定描述符执行读取操作。在其他情况下,select根本不返回,因为我没有提到超时。在接收多播时,始终绑定到
    INADDR\u ANY
    。在Linux中,如果绑定到特定接口,将无法接收multicast.IP_multicast_,如果设置了为套接字发送相关IGMP消息的接口。没有别的了。
                FD_ZERO(&sockfd_set);
                FD_SET(svr->sockfd, &sockfd_set);
                FD_SET(svr->notify_pipe[0], &sockfd_set);
                printf("before select\n");
                select(max_fd + 1, &sockfd_set, NULL, NULL, NULL);
                printf("after select\n");