Opened 11 years ago

Last modified 7 years ago

#6446 reopened Bugs

Mulicast receiver does not work

Reported by: dieter.mayer@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.47.0 Severity: Problem
Keywords: Multicast Cc:

Description

Quickfast 1.4 uses Boost 1.47.0 to receive FAST Marketdata via Multicast. We are developing an EBS (Eurex) Market Data Feed on Red Hat Linux 5.7 64 Bit. Starting the InterpretApplication from quickfast no data are received. Starting in parallel a Java based multicast reader, then the data are then received in the InterpretApplication. I have also tried it with the boost test program: http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/example/multicast/receiver.cpp with the same behaviour

best regards

Dieter

Change History (9)

comment:1 by chris_kohlhoff, 10 years ago

Resolution: worksforme
Severity: ShowstopperProblem
Status: newclosed

Most likely you have multiple network cards and the default route does not match the interface you need to use for the multicast group. You need to either:

  • get your system administrator to add a route for the multicast group that uses the correct device; or
  • change your code to use the two-argument join_group constructor that lets you specify the interface.

Most likely the Java application does the latter. As multicast group subscriptions are system-wide, this makes your application work too. However, the first option is IMHO the preferred approach.

comment:2 by dieer.mayer@…, 10 years ago

Chris,

have you tried the testprogramm ? have you understood my problem report ?

best regards

Dieter

comment:3 by chris_kohlhoff, 10 years ago

I understood your problem report... The behaviour you describe is consistent with a routing issue.

comment:4 by anonymous, 10 years ago

Hi, A Java mcast reader wirks fine, a pure C mcast readers works also, only The boost base reader is a problem

Best regards Dieter

comment:5 by chris_kohlhoff, 10 years ago

As I said, it looks like a routing issue. Please note my first comment, in particular:

Most likely the Java application [uses the equivalent of the two-argument join_group constructor]. As multicast group subscriptions are system-wide, this makes your application work too.

You need to explore one of the two options I outlined in my first comment.

comment:6 by cgarcia, 10 years ago

Boost examples are wrong, doesn't work in linux for machines with several network interfaces. Proper truly working code snippet for receiving on network interface 1.2.3.4:

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);

comment:7 by cgarcia, 10 years ago

Sorry for the improper code formatting. Repeated here:

    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);

comment:8 by chris_kohlhoff, 10 years ago

Thanks for your comment, but the examples are not wrong. The approach shown in the examples works on multi-homed hosts provided you have configured the host's routing table correctly. However, you are correct that the two-argument join_group constructor is a valid alternative (although IMHO not generally preferred) approach, as I indicated in comment 1.

comment:9 by Ludwig Schultze, 7 years ago

Resolution: worksforme
Status: closedreopened

Request to reopen and fix receiver.cpp.

sender.cpp is ok. Like Chris wrote, the routing table of the OS can be used to select the network interface through which to send outgoing multicast traffic. But sending was never the topic of this bug.

There might exist operating systems that use the routes for outgoing multicast traffic to also have the network interfaces join multicast groups for incoming traffic. At least Linux is not one of them.

As a result, the following does not work on Linux. It is the shell transcript of an attempt to use the kernel routing tables to make receiver.cpp work as suggested by Chris:

# MCAST_IP=<your multicast group>
# ETH0_IP=<your IP of eth0 network interface>
# sudo route add $MCAST_IP dev eth0
# ./receiver $ETH0_IP $MCAST_IP

This does not detect multicast packets of group MCAST_IP that arrive at eth0.

The packets are only detected if receiver is invoked as

./receiver 0.0.0.0 $MCAST_IP 

but this receives also packets to the same port in all other multicast groups currently joined. Most likely because 0.0.0.0, being IPADDR_ANY, matches all multicast groups.

Thanks to cgarcia for sharing the correct code.

Note: See TracTickets for help on using tickets.