Multicast between 2 applications on same host(macOS). The example is based on launching 2 applications Appli_A who join the same multicast group and are listening of an incoming datagram packet which is beeing send by the application Appli_B but there is only one of the 2 applications Appli_A receiving the packet and not both. Since the implementation is platform dependent and I'm using macOS I had to change some commands that's why I use SO_REUSEPORT instead of SO_REUSEADDRES But it still won't work. Here's a small example:
Appli_A
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct sockaddr_in localSock;
struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];
void sigint_routine_handler(int param){
if(close(sd) == 0)
printf("hSocket closed\n");
else
printf("Error closing hSocket\n");
}
int main(int argc, char *argv[])
{
if(signal(SIGINT, sigint_routine_handler) == SIG_ERR)
printf("ERROR: Installing suspend handler SIGINT\n");
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
/* Enable SO_REUSEPORT to allow multiple instances of this */
/* application to receive copies of the multicast datagrams. */
int reuse = 1;
if(setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&reuse, sizeof(reuse)) < 0)
{
close(sd);
exit(1);
}
/* Since I'm using htonl(INADDR_ANY) I'm Binding the socket to all available interfaces */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(54011);
localSock.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
{
close(sd);
exit(1);
}
/* Join the multicast group 235.73.158.23 */
group.imr_multiaddr.s_addr = inet_addr("235.73.158.23");
group.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
close(sd);
exit(1);
}
/* Read from the socket. */
datalen = sizeof(databuf);
if(read(sd, databuf, datalen) < 0)
{
perror("Reading datagram message error");
close(sd);
exit(1);
}
else
{
printf("Reading datagram message...OK.\n");
printf("The message from multicast server is: \"%s\"\n", databuf);
}
if(close(sd) < 0)
printf("Error close socket descriptio\n");
return 0;
}
Appli_B
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct in_addr localInterface;
struct sockaddr_in groupSock;
int sd;
char databuf[50] = "Multicast test message$";
int datalen = sizeof(databuf);
int main(int argc, char *argv[])
{
/* Create a datagram socket on which to send. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
/* README Normally here should I specifiy the Multicast-adress of the group for the outgoing
Datagrampacket, but it won't work if I specify this Multicast-adress "235.73.158.23"*/
groupSock.sin_addr.s_addr = htonl(INADDR_ANY);
groupSock.sin_port = htons(54011);
/* Set local interface for outbound multicast datagrams. */
/* The IP address specified must be associated with a local, */
/* multicast capable interface -> I have checked the interface, it is Multicast capable */
localInterface.s_addr = inet_addr("192.168.1.5");
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0)
{
perror("Setting local interface error");
exit(1);
}
else
printf("Setting the local interface...OK\n");
/* Send a message to the multicast group specified by the*/
/* groupSock sockaddr structure. */
int datalen = 50;
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0){
perror("Sending datagram message error");
}
else
printf("Sending datagram message...OK\n");
return 0;
}
UPDATE
I have tried it on ubuntu linux 16.04, there everything works fine. I changed SO_REUSEPORT to SO_REUSEADDR and the Multicast-address of the outgoing Datagrampacket of Appli_B to the Multicastgroup specified in Appli_A, if I do this on MACOS none of the 2 Appli_A applications receives the datagram packet, in case that the interface might not have a multicast address I followed this blog but it still won't work under MacOS.