siddhant
siddhant

Reputation: 837

How to receive multicast packets from already subscribed group?

In my ubuntu 16.04 system I ran the following program:

#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>


#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 256

main(int argc, char *argv[])
{
    struct sockaddr_in addr;
    int fd, nbytes,addrlen;
    struct ip_mreq mreq;
    char msgbuf[MSGBUFSIZE];

    u_int yes=1;          

    if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
        perror("socket");
        exit(1);
    }

    if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
        perror("Reusing ADDR failed");
        exit(1);
    }    

    memset(&addr,0,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=inet_addr(HELLO_GROUP); 
    addr.sin_port=htons(HELLO_PORT);

    /* bind to receive address */
    if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
        perror("bind");
        exit(1);
    }

    mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
    mreq.imr_interface.s_addr=htonl(INADDR_ANY);
    if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
        perror("setsockopt");
        exit(1);
    }
}

This program just subscribes my system to receive multicast UDP packets from group 225.0.0.37

On another system in my local network I have another program which periodically sends packets to this group

After subscribing to the group using the above program i verified that i am getting UDP packets destined to 225.0.0.37 from wireshark

I want to read these incoming packets through another program. And I don't want to use raw sockets. Following is the other program which I have written:

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>

using boost::asio::ip::udp;

static const int max_length = 1024;

char data_[max_length];

void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd)
{
    std::cout.write(data_, bytes_recvd);
}

int main(int argc, char* argv[])
{
    try
    {

    boost::asio::io_service io_service;

    udp::endpoint local_endpoint = boost::asio::ip::udp::endpoint(
        boost::asio::ip::address::from_string("225.0.0.37"), boost::lexical_cast<int>("12345"));
    std::cout << "Bind " << local_endpoint << std::endl;

    udp::socket socket(io_service);
    socket.open(local_endpoint.protocol());
    socket.set_option(udp::socket::reuse_address(true));
    socket.bind(local_endpoint);

    socket.async_receive(
        boost::asio::buffer(data_, max_length),
        boost::bind(&handle_receive_from,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

    io_service.run();
    }
    catch (std::exception& e)
    {
    std::cerr << e.what() << std::endl;
    }

    return 0;
}

This program doesn't get any data even though i see packets coming through wireshark. What am I doing wrong? Is getting data even possible? The overall questions is this: Can I subscribe to a multicast group in one program and receive packets in another?

Upvotes: 2

Views: 568

Answers (1)

jfly
jfly

Reputation: 7990

It depends.

If your first program exits soon, then os will close the socket, send the IGMP Leave, so your second program wouldn't receive any multicast packets. So you should keep the first program running(add a function to block forever) so that it doesn't leave the multicast group.

The linux kernel in fact tracks group membership per socket, seems it doesn't use this to filter multicast packets. So you can subscribe to a multicast group in one program and receive packets in another until unsubscription(works on my Ubuntu 14.04). Not sure whether this strategy will change, but on my OS X 10.10, it does not allow such thing.

Upvotes: 1

Related Questions