Reputation: 113
I'm trying to write multicast server. I've two questions:
How to send multicast announcements on multiple interfaces like ethernet/ wifi interface. Do I need to create multiple sockets for each interface and bind?
When bind socket with INADDR_ANY address, descriptor is ready to do I/O operation (using select call )but when I bind with specific interface address e.g ethernet/wifi then descriptor is not ready to perform any operation it is stuck at select api only. So what is the difference between binding a socket with default address (INADDR_ANY) or specific interface address?
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()");
}
In thread waiting for descriptors to ready for I/O (basically all are read file descriptors)
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");
When socket id bind with INADD_ANY address select will returns and I'm able to read with file descriptor but when bind with specific interface then select never returns coz there is no file descriptors available to read.
Upvotes: 2
Views: 3611
Reputation: 311008
- How to send multicast announcements on multiple interfaces like ethernet/ wifi interface. Do I need to create multiple sockets for each interface and bind?
No. Loop over the network interfaces and call setsockopt()
with an appropriate join parameters for each interface in turn. You only need one socket.
- When bind socket with INADDR_ANY address, descriptor is ready to do I/O operation (using select call)
That's not correct. Your code only checks for readability.
but when I bind with specific interface address e.g ethernet/wifi then descriptor is not ready to perform any operation
Again that's not correct. You're only checking for readability, not 'any operation'. All this means is that no multicasts are coming in via the address you bound to.
it is stuck at select api only. So what is the difference between binding a socket with default address (INADDR_ANY) or specific interface address?
It determines the IP address you send and receive via.
Upvotes: 1
Reputation: 2335
Binding a socket with a specific address is a generic way to lock it down to a device. This method is a bit old-fashion, since addresses can be changed on a device after your program has started up. In general I would recommend to bind to INADDR_ANY.
You can change the output multicast device on a socket whenever you want.
Options to consider:
man 7 ip :
IP_MULTICAST_ALL - deliver to all devices (default 1)
IP_MULTICAST_IF - I'm pretty sure this only sets the output device
man 7 socket :
SO_BINDTODEVICE
Just play a little with the options and see what the result is
Upvotes: 0