Boost logo

Boost Users :

Subject: [Boost-users] [asio] Multicast Receive with multiple network cards (nics)
From: Ryan McConnehey (mccorywork_at_[hidden])
Date: 2010-06-21 12:57:13


 From all the different material I've read, receiving multicast network
packets on multiple network cards is easy. Just bind to the network
card who you want to receive the packet and join the multicast group. I
understand that because Windows XP (which I use), has a "Weak End
System" ("Weak E/S") model; meaning sending out on a specific network
card is a lot more difficult. I have provided a sample program that's
been slightly modified from the multicast receive example in Asio
documentation. This program doesn't receive packets from any interface
specified. It will only receive information on the primary network card.

I'm not sure what is going on and would greatly appreciate any help.

Ryan


// SampleAsioReceive.cpp : Defines the entry point for the console application.
//

#include <map>
#include <iostream>
#include <string>

//Boost Includes
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>

class RdssReceive {
public:

RdssReceive(
  boost::asio::io_service* ioService ,
        const boost::asio::ip::address& listenAddress,
        const boost::asio::ip::address& mcAddr,
        unsigned int mcPort = 0 /* 31001 */ )
: m_MulticastPort( mcPort ) // multicast port
, m_MulticastAddress( mcAddr ) // multicast ip addr
, m_Socket( *ioService )
, m_InterfaceAddress( listenAddress )
, m_numRec(0)
{
  try { // Create the socket so that multiple may be bound to the same address.
    boost::asio::ip::udp::endpoint listenEndpoint( listenAddress, static_cast<unsigned short>(m_MulticastPort) );
    m_Socket.open(listenEndpoint.protocol());
    m_Socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));
    
    boost::system::error_code ec;
    m_Socket.bind(listenEndpoint, ec);

    // Join the multicast group.
    m_Socket.set_option( boost::asio::ip::multicast::join_group(m_MulticastAddress) );

    m_Socket.async_receive_from(
      boost::asio::buffer(m_Data, max_size),
      m_SenderEndpoint,
                        boost::bind( &RdssReceive::handleReceiveFrom,
        this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
  }
  catch( std::exception& e ) {
    std::cerr << "Create error. " << e.what() << std::endl;
  }
}

void handleReceiveFrom( const boost::system::error_code& error, size_t bytes_recvd ){
  if (!error) {
    std::cout << "Msg received: " << m_numRec++ << std::endl;
        }
  else {
    std::cerr << "handleReceiveFrom error -> " << error.value() << std::endl;
  }

  try {
    m_Socket.async_receive_from(
      boost::asio::buffer(m_Data, max_size),
      m_SenderEndpoint,
      boost::bind(&RdssReceive::handleReceiveFrom, this,
        boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred));
  }
  catch ( std::exception& e ) {
    std::cerr << "Error in handleReceiveFrom during async_receive_from. " << e.what() << std::endl;
  }
  catch ( ... ) {
    std::cerr << "Unknow error in handleReceiveFrom during async_receive_from." << std::endl;
  }
}

virtual ~RdssReceive() {
  std::cout << "RdssReceive destructor: " << m_MulticastAddress.to_string() << ":" << m_MulticastPort << std::endl;
  m_Socket.shutdown(boost::asio::ip::tcp::socket::shutdown_receive);
  m_Socket.close();
}

  typedef unsigned long long uint64_t;
  static const int max_size = 1500;
private:
        boost::asio::ip::udp::socket m_Socket;
        boost::asio::ip::udp::endpoint m_SenderEndpoint;

        unsigned int m_MulticastPort;
        boost::asio::ip::address m_MulticastAddress;
        boost::asio::ip::address m_InterfaceAddress;

  char m_Data[max_size];
  int m_numRec;
};

std::string ipAddr = "";
int port = 9252;
std::string mcAddr = "225.6.6.254";
int main(int argc, char* argv[])
{
    boost::asio::io_service ioServ;

    if ( argc > 1 ) {
        ipAddr = argv[1];
        port = atoi(argv[2]);
    }
    std::cout << "IpAddress: " << ipAddr << " Port: " << port << std::endl;
    RdssReceive rdssReceive(
      &ioServ,
      boost::asio::ip::address::from_string(ipAddr),
      boost::asio::ip::address::from_string(mcAddr),
      port );

    ioServ.run();

    //std::cout << "Press key and return to exit." << std::endl;
    char cc;
    std::cin >> cc;

        return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net