【发布时间】:2023-03-28 15:30:01
【问题描述】:
我正在尝试编写多播服务器。我有两个问题:
如何在以太网/wifi 接口等多个接口上发送多播公告。我需要为每个接口创建多个套接字并绑定吗?
-
当使用 INADDR_ANY 地址绑定套接字时,描述符已准备好执行 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()"); }
在线程中等待描述符为 I/O 做好准备(基本上都是读取文件描述符)
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");
当套接字 id 与 INADD_ANY 地址绑定时,select 将返回,并且我可以使用文件描述符进行读取,但是当与特定接口绑定时,select 永远不会返回,因为没有可读取的文件描述符。
【问题讨论】:
-
我已将套接字描述符添加到 sockfd_set 和 select 将在与 INADDR_ANY 绑定时返回 1,之后我使用 FD_ISSET 检查套接字描述符并对特定描述符执行读取操作。在其他情况下,选择根本没有返回,因为我没有提到超时。
-
接收多播时,始终绑定到
INADDR_ANY。在 Linux 中,如果绑定到特定接口,将无法接收多播。
标签: c sockets networking udp multicast