Opened 11 years ago
Last modified 7 years ago
#6446 reopened Bugs
Mulicast receiver does not work
Reported by: | 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 , 10 years ago
Resolution: | → worksforme |
---|---|
Severity: | Showstopper → Problem |
Status: | new → closed |
comment:2 by , 10 years ago
Chris,
have you tried the testprogramm ? have you understood my problem report ?
best regards
Dieter
comment:3 by , 10 years ago
I understood your problem report... The behaviour you describe is consistent with a routing issue.
comment:4 by , 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 , 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 , 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 , 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 , 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 , 7 years ago
Resolution: | worksforme |
---|---|
Status: | closed → reopened |
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.
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:
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.