2

I have a listener like this:

 receiver r(io_service,
               boost::asio::ip::address::from_string(argv[1]),
               boost::asio::ip::address::from_string(argv[2]));

If I run the code with parameters

./BoostAsioMCReceiver 0.0.0.0 239.255.0.1

the listener gets all multicast packets fine from the sender (on a different computer). However, if I actually enter the ethernet IP address of the machine, for example

./BoostAsioMCReceiver 172.22.1.5 239.255.0.1

The receiver doesn't seem to get any packets. I need to do this because the computer has more than one ethernet card, and I need to be certain that packets go out a given NIC and by extension the correct switch.

Receiver looks like this:

receiver(boost::asio::io_service& io_service,
         const boost::asio::ip::address& listen_address,
         const boost::asio::ip::address& multicast_address)
    : socket_(io_service)
{
    boost::asio::ip::udp::endpoint listen_endpoint(
        listen_address, multicast_port);
    socket_.open(listen_endpoint.protocol());
    socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
    socket_.bind(listen_endpoint);

    socket_.set_option(
        boost::asio::ip::multicast::join_group(multicast_address));

    socket_.async_receive_from(
        boost::asio::buffer(data, max_length), sender_endpoint,
        boost::bind(&receiver::handle_receive_from, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
}

private:
boost::asio::ip::udp::socket socket;
boost::asio::ip::udp::endpoint sender_endpoint;

Why is this happening, and what is the suggested fix?

Thanks.

Ivan
  • 5,964
  • 9
  • 52
  • 103

2 Answers2

4

I struggled with this issue for some time. I finally found this explanation. This code from that post caused my socket to bind to the correct interface:

std::string address_listen = "1.2.3.4";
std::string address_mcast = "224.0.0.0";
unsigned short address_port = 50000;
boost::system::error_code ec;
boost::asio::ip::address listen_addr = boost::asio::ip::address::from_string(address_listen, ec);
boost::asio::ip::address mcast_addr = boost::asio::ip::address::from_string(address_mcast, ec);
boost::asio::ip::udp::endpoint listen_endpoint(mcast_addr, address_port);
socket.open(listen_endpoint.protocol(), ec); // boost::asio::ip::udp::socket
socket.set_option(boost::asio::ip::udp::socket::reuse_address(true), ec);
socket.bind(listen_endpoint, ec);
socket.set_option(boost::asio::ip::multicast::join_group(mcast_addr.to_v4(), listen_addr.to_v4()), ec);

I believe this post on stackoverflow also describes the same solution.

Community
  • 1
  • 1
trukvl
  • 783
  • 5
  • 13
2

The listening address for boost.asio multicast example is actually not a local IP address. It could be a multicast group address or the wildcard address "0.0.0.0".

The address binding is working as a filtering purpose. e.g. you could set it to the exact multicast group address () for receiving packets from the group only.

For your case, you could run the command like below,

./BoostAsioMCReceiver 239.255.0.1 239.255.0.1

please see more explanation here [What does it mean to bind a multicast (UDP) socket?.

Community
  • 1
  • 1
qduyang
  • 353
  • 1
  • 8