2

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.

Daniel B
  • 91
  • 1
  • 5
  • I tried to compile these programs so that I could try them out on my machine, but neither of them compile because some of the code is missing. Since I can't compile the programs I can't run them, and since I can't run them I can't diagnose them. – Jeremy Friesner Jan 11 '20 at 03:47
  • @Jeremy Friesner I updated the code accordingly – Daniel B Jan 11 '20 at 08:41
  • SO_REUSEPORT only works if everybody sets it. However if the second application only sends, it doesn't need to join the group, or use the same port. – user207421 Jan 11 '20 at 09:48
  • And what do you mean by '*simulate* multicast'? There is no simulation here. – user207421 Jan 11 '20 at 10:59

0 Answers0