C++ How can i join to a multicast mpeg stream?

6.9k views Asked by At

How can i manage to join a multicast mpeg stream group with an address of udp://@224.1.50.15:1234? What i want to manage is just to make a connection with the stream server to make the server become aware of that i am interested in this multicast group to make the server to send me the stream packets for a period of a time.

For an example: I am not receiving any packets from this multicast group until i establish a connection to the group with VLC Player. Even after i close the VLC Player i keep receiving packets from the group for a short period of time. What i am trying to do is to receive the packets without the help of VLC Player or any other third party application.

How can i manage to make a connection with this group for the purpose above. If it is even possible?

P.S: I have 4 network interfaces installed.

Thank you!

As the recommendation of Zaboj Campula in his answer in this page; i changed the code as below. Which gives me an error 10093.

struct ip_mreq {
    struct in_addr imr_multiaddr;   /* IP multicast address of group */
    struct in_addr imr_interface;   /* local IP address of interface */
};
SOCKET        s;
SOCKADDR_IN    localif;
struct ip_mreq mreq;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
localif.sin_family = AF_INET;
localif.sin_port = htons(1234);
localif.sin_addr.s_addr = INADDR_ANY;
bind(s, (SOCKADDR *)&localif, sizeof(localif));
mreq.imr_interface.s_addr = INADDR_ANY; //Writing here my local ip didn't change the result.
mreq.imr_multiaddr.s_addr = inet_addr("224.1.50.15");
int rc = NO_ERROR;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Join the group
rc = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
if (rc == SOCKET_ERROR)
{
    printf("JoinMulticastGroup: setsockopt failed with error code %d\n", WSAGetLastError());
}
else
{
    printf("Joined group: ");
    //PrintAddress(group->ai_addr, group->ai_addrlen);
    printf("\n");
}
2

There are 2 answers

0
swartkatt On BEST ANSWER

Ok, I managed to resolve my issue with the help of the book Multicast Sockets Practical Guide for Programmers which is written by David Makofske & Kevin Almeroth

Thank's goes to the writers and Zaboj Campula for their efforts.

I hope this post and the answer will help many others in the future. The working code is written below! Compiled with Visual Studio 2017 RC (Console Empty C project)

int sock;                     /* socket descriptor */
int flag_on = 1;              /* socket option flag */
struct sockaddr_in mc_addr;   /* socket address structure */
char recv_str[MAX_LEN + 1];     /* buffer to receive string */
int recv_len;                 /* length of string received */
struct ip_mreq mc_req;        /* multicast request structure */
char* mc_addr_str;            /* multicast IP address */
unsigned short mc_port;       /* multicast port */
struct sockaddr_in from_addr; /* packet source */
unsigned int from_len;        /* source addr length */
WSADATA wsaData;              /* Windows socket DLL structure */

mc_addr_str = "224.1.50.15";      /* arg 1: multicast ip address */
mc_port = atoi("1234");    /* arg 2: multicast port number */

                            /* validate the port range */
if ((mc_port < MIN_PORT) || (mc_port > MAX_PORT)) {
    fprintf(stderr, "Invalid port number argument %d.\n",
        mc_port);
    fprintf(stderr, "Valid range is between %d and %d.\n",
        MIN_PORT, MAX_PORT);
    exit(1);
}

/* Load Winsock 2.0 DLL */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
    fprintf(stderr, "WSAStartup() failed");
    exit(1);
}

/* create socket to join multicast group on */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    perror("socket() failed");
    exit(1);
}

/* set reuse port to on to allow multiple binds per host */
if ((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&flag_on,
    sizeof(flag_on))) < 0) {
    perror("setsockopt() failed");
    exit(1);
}

/* construct a multicast address structure */
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
mc_addr.sin_port = htons(mc_port);

/* bind to multicast address to socket */
if ((bind(sock, (struct sockaddr *) &mc_addr,
    sizeof(mc_addr))) < 0) {
    perror("bind() failed");
    exit(1);
}

/* construct an IGMP join request structure */
mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
mc_req.imr_interface.s_addr = htonl(INADDR_ANY);

/* send an ADD MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
    (char*)&mc_req, sizeof(mc_req))) < 0) {
    perror("setsockopt() failed");
    exit(1);
}

for (;;) {          /* loop forever */

                    /* clear the receive buffers & structs */
    memset(recv_str, 0, sizeof(recv_str));
    from_len = sizeof(from_addr);
    memset(&from_addr, 0, from_len);

    /* block waiting to receive a packet */
    if ((recv_len = recvfrom(sock, recv_str, MAX_LEN, 0,
        (struct sockaddr*)&from_addr, &from_len)) < 0) {
        perror("recvfrom() failed");
        exit(1);
    }

    /* output received string */
    printf("Received %d bytes from %s: ", recv_len,
        inet_ntoa(from_addr.sin_addr));
    printf("%s", recv_str);
}

/* send a DROP MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
    (void*)&mc_req, sizeof(mc_req))) < 0) {
    perror("setsockopt() failed");
    exit(1);
}

closesocket(sock);
WSACleanup();  /* Cleanup Winsock */
1
Zaboj Campula On

UDP sockets do not support connections. It is not possible to call listen and accept on an UDP socket. You can directly read from the UDP socket when it is bound to a local port.

The socket option IP_ADD_MEMBERSHIP joins the socket to a multicast group.

 struct ip_mreq m;
 m.imr_interface.s_addr = inet_addr(loca_ip_address);
 m.imr_multiaddr.s_addr = inet_addr("224.1.50.15");
 setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&m, sizeof(m));

You ca find a full example at http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancedmulticast9a.html