Reputation: 837
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
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