Receving multiple multicast feeds on the same port - C, Linux


Receving multiple multicast feeds on the same port - C, Linux



I have an application that is receiving data from multiple multicast sources on the same port. I am able to receive the data. However, I am trying to account for statistics of each group (i.e. msgs received, bytes received) and all the data is getting mixed up. Does anyone know how to solved this problem? If I try to look at the sender's address, it is not the multicast address, but rather the IP of the sending machine.

I am using the following socket options:

struct ip_mreq mreq;          mreq.imr_multiaddr.s_addr = inet_addr("224.1.2.3");          mreq.imr_interface.s_addr = INADDR_ANY;          setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); 

and also:

setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)); 

I appreciate any help!!!


How to track the memory usage in C++

1:

How to completely wipe rubygems along with rails etc
[Edited to clarify this bind() may in fact include a multicast address.]. C functions invoked as threads - Linux userland program So the application is joining several multicast groups, and receiving messages sent to any of them, to the same port. How to detect pending system shutdown on Linux?SO_REUSEPORT allows you to bind several sockets to the same port. How can I setup my Netbeans IDE for making Java ME applications?Besides the port, bind() needs an IP address. Buffering of stream dataINADDR_ANY is a catch-all address, although an IP address may also be used, including a multicast one. PHP Segmentation fault when started from crondIn this case, only packets sent to this IP will be delivered to the socket. waiting for 2 different events in a single threadI.e. you must create several sockets, one for each multicast group. bind() each socket to the (group_addr, port), AND join group_addr. Then data addressed to different groups will show up on different sockets, and you'll be able to distinguish it this way.. I tested this the following works on FreeBSD:.
#include <sys/socket.h> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/param.h> #include <unistd.h> #include <errno.h>  int main(int argc, const char *argv[]) {     const char *group = argv[1];      int s = socket(AF_INET, SOCK_DGRAM, 0);     int reuse = 1;     if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) == -1) {         fprintf(stderr, "setsockopt: %d\n", errno);         return 1;     }      /* construct a multicast address structure */     struct sockaddr_in mc_addr;     memset(&mc_addr, 0, sizeof(mc_addr));     mc_addr.sin_family = AF_INET;     mc_addr.sin_addr.s_addr = inet_addr(group);     mc_addr.sin_port = htons(19283);      if (bind(s, (struct sockaddr*) &mc_addr, sizeof(mc_addr)) == -1) {         fprintf(stderr, "bind: %d\n", errno);         return 1;     }      struct ip_mreq mreq;     mreq.imr_multiaddr.s_addr = inet_addr(group);     mreq.imr_interface.s_addr = INADDR_ANY;     setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));      char buf[1024];     int n = 0;     while ((n = read(s, buf, 1024)) > 0) {         printf("group %s fd %d len %d: %.*s\n", group, s, n, n, buf);     } } 
If you run several such processes, for different multicast addresses, and send a message to one of the addresses, only the relevant process will receive it. Of course, in your case, you probably will want to have all the sockets in one process, and you'll have to use select or poll or equivalent to read them all..

2:

After any years facing this linux strange behaviour, and using the bind workaround describe in previous answers, I realize this the ip(7) manpage describe a possible quick fix :.
IP_MULTICAST_ALL (since Linux 2.6.31) This option must be used to modify the delivery policy of multicast messages to sockets bound to the wildcard INADDR_ANY address. The argument is a boolean integer (defaults to 1). If set to 1, the socket will receive messages from all the groups this have been joined globally on the whole system. Otherwise, it will deliver messages only from the groups this have been explicitly joined (for case via the IP_ADD_MEMBERSHIP option) on this particular socket..
Then you must activate the filter to receive messages of joined groups using :.
int mc_all = 0; if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_ALL, (void*) &mc_all, sizeof(mc_all))) < 0) {     perror("setsockopt() failed"); } 

3:

Use setsockopt() and IP_PKTINFO or IP_RECVDSTADDR depending on your platform, assuming IPv4. This combined with recvmsg() or WSARecvMsg() allows you to find the source and destination address of every packet.. Unix/Linux, note FreeBSD uses IP_RECVDSTADDR whilst both support IP6_PKTINFO for IPv6.. Windows, also has IP_ORIGINAL_ARRIVAL_IF.

4:

Replace. mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);. with. mc_addr.sin_addr.s_addr = inet_addr (mc_addr_str);. it's guidance for me (linux), for each application i receive separate mcast stream from separate mcast group on one port.. Also you must look into VLC player source, it show many mcast iptv channel from different mcast group on one port, although i dont know, how it separetes channel..

5:

I have had to use multiple sockets each looking at different multicast group addresses, and then count statistics on each socket individually.. If there is a way to see the "receiver's address" as mentioned in the answer above, I can't figure it out.. One important point this also took me awhile - when I bound each of my individual sockets to a blank address like most python examples do:.
sock[i].bind(('', MC_PORT[i]) 
I got all the multicast packets (from all multicast groups) on each socket, which didn't help. To fix this, I bound each socket to it's own multicast group.
sock[i].bind((MC_GROUP[i], MC_PORT[i])) 
And it then worked..

6:

IIRC recvfrom() gives you a different read address/port for each sender.. You must also put a header in each packet identifying the source sender..

7:

The Multicast address will be the receiver's address not sender's address in the packet. Look at the receiver's IP address..


92 out of 100 based on 47 user ratings 402 reviews