/* compiled with
  g++ -o udpclient udpclient2.cpp -lboost_system -lboost_thread
*/

#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];

udp::endpoint sender_endpoint;

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
  {
    if (argc != 3)
    {
      std::cerr << "Usage: client <host> <port>" << std::endl;
      return 1;
    }

    boost::asio::io_service io_service;

    udp::endpoint local_endpoint = boost::asio::ip::udp::endpoint(
	  boost::asio::ip::address::from_string(argv[1]), boost::lexical_cast<int>(argv[2]));
    std::cout << "Local bind " << local_endpoint << std::endl;
 
// MODE 1: WORKS  
//    udp::socket socket(io_service, local_endpoint);

// MODE 2: WORKS
//    udp::socket socket(io_service, udp::endpoint(udp::v4(), boost::lexical_cast<int>(argv[2]) )),

// MODE 3: WORKS
    udp::socket socket(io_service);
    socket.open(udp::v4());
    socket.bind(local_endpoint);
///////////////
    
    
    socket.async_receive_from(
        boost::asio::buffer(data_, max_length), sender_endpoint,
        boost::bind(&handle_receive_from,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    // run
    boost::thread t = boost::thread (boost::bind(&boost::asio::io_service::run, &io_service));

    while(1) { }
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}