boost asio asynchronous udp client, handle never triggered

  asio, asynchronous, boost, c++, udp

I’ve been struggling with this for almost 2 weeks now and I think it’s time for me to
ask for help.

I need to get data from a server running on a fpga. The server has been written
by someone who’s unfortunately no longer working with us. Though the server
works as expected because when I send a request I can see with wireshark the
expected content. Wireshark is running on the computer that executes the c++ udp
client.

The five first lines (1..5) in the table are the ones I send. Every other lines,
out of ICMP ones, are sent by the server. The server send messages over multiple
ports according to the type of message. I think sending data is properly working
otherwise I would not get line 6 to xxx.

The problem is that my client never receives anything. The handle is never
triggered and I can’t find why.

Can you please help me one this one.

Thank you very much for your time.

Olivier

"No." "Source" "Destination" "Protocol" "Length" "Info" "port"
"1" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "1"
"2" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "2"
"3" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "3"
"4" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "4"
"5" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "5"
"6" "192.168.0.1" "192.168.0.254" "UDP" "60" "50000 → 32776 Len=8" "6"
"7" "192.168.0.1" "192.168.0.254" "UDP" "74" "51000 → 32776 Len=32" "7"
"8" "192.168.0.254" "192.168.0.1" "ICMP" "102" "Destination unreachable (Communication administratively filtered)" "8"
"9" "192.168.0.1" "192.168.0.254" "UDP" "466" "52000 → 32776 Len=424" "9"
"10" "192.168.0.254" "192.168.0.1" "ICMP" "494" "Destination unreachable (Communication administratively filtered)" "10"
"12" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "12"
"13" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "13"
"14" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "14"
"15" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "15"
"17" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "17"
"18" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "18"
"19" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "19"
"20" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "20"
"22" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "22"
"23" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "23"
"24" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "24"
"25" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "25"
"26" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "26"
"27" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "27"
#include "udp_client.hxx"
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
//#include <thread>
#include <boost/bind/bind.hpp>
#include <boost/asio.hpp>
#include <ctime>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "udp_constants.hxx"
using  boost::asio::ip::udp;

udp_client::udp_client(boost::asio::io_context &io) :
  io(io),
  socket(io)
{
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x01, 0x00, 0x7a, 0x11, 0xfe});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x02, 0x00, 0x7a, 0x11, 0xfe});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
  filename="/home/lemaire/data.dat";
  set_acquisition_and_get_data(datagrams);
}


udp_client::~udp_client()
{
  socket.close();
  // close file
  output_stream.close();
  // inform user
  std::cout << "udp server destructor" << std::endl;
}


std::vector<unsigned char> udp_client::ui64_to_vector(uint64_t w)
{
  std::vector<unsigned char> vec(8, 0x0);
  char c;
  size_t d{0};
  for(int i{0}; i<8; i++)
  {
    d = (8-1-i)*8;
    c = static_cast<unsigned char>(w >> d);
    vec[i] = c;
  }
  return vec;
}

bool udp_client::send_data(std::vector<std::vector<unsigned char>>& datagrams)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  udp::resolver resolver(io);
  udp::endpoint endpoint_tx =
        *resolver.resolve(udp::v4(),
                          udp_constants::ip::fpga,
                          "5").begin();
  try
  {
    std::cout << "send data" << std::endl;
    socket.open(udp::v4());
    for(auto datagram: datagrams)
      socket.send_to(boost::asio::buffer(datagram), endpoint_tx);
  }
  catch (const boost::system::system_error& e)
  {
    std::cout << e.what() << std::endl;
  }
  socket.close();
  return true;
}

bool udp_client::set_acquisition_and_get_data(std::vector<std::vector<unsigned char>>& datagrams)
{
  std::cout << __PRETTY_FUNCTION__ << " begin" << std::endl;
  send_data(datagrams);
  start_receive();
  return true;
}

void udp_client::start_receive()
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  output_stream.open(filename,
                     std::ofstream::out |
                     std::ofstream::trunc |
                     std::ofstream::binary);
  try {
    socket.open(udp::v4());
  }  catch (std::exception& e) {
    std::cerr << "erreur ouverture: " << e.what() << std::endl;
  }
  receive_data();
  std::cout << __PRETTY_FUNCTION__ << " socket data started" << std::endl;

  return;
}

void udp_client::receive_data()
{
  std::cout << "socket opened: " << socket.is_open() << std::endl;
  socket.async_receive_from
      (boost::asio::buffer(recv_buf),
       endpoint_rx,
       boost::bind(&udp_client::handle_data, this,
                   boost::asio::placeholders::error,
                   boost::asio::placeholders::bytes_transferred));
  std::cout << "async receive from started" << std::endl;
}

void udp_client::handle_data(const boost::system::error_code& error,
                             std::size_t bytes_transferred)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  if(!error)
  {
    output_stream.write(recv_buf.data(), bytes_transferred);
    receive_data();
  }
  else
  {
    std::cerr << "handle daq start error: " << error.message() << std::endl;
  }
  return;
}
// file: udp_client.hxx 
#ifndef UDP_CLIENT_HXX
#define UDP_CLIENT_HXX
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
#include <list>
#include <ctime>
#include <string>
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/thread.hpp>
#include <boost/array.hpp>
#include <boost/asio/strand.hpp>
#include <boost/bind/bind.hpp>
using  boost::asio::ip::udp;

class udp_client
{
public:
  udp_client(boost::asio::io_context& io);
  ~udp_client();

  void handle_receive(const boost::system::error_code& error,
                      std::size_t bytes_transferred);
  void start_receive();
  static std::vector<unsigned char> ui64_to_vector(uint64_t);
  bool send_data(std::vector<std::vector<unsigned char>>& datagrams);
  bool set_acquisition_and_get_data(std::vector<std::vector<unsigned char>>& datagrams);
private:
  // strand
  boost::asio::io_context& io;
  std::vector<std::vector<unsigned char>> datagrams;
  std::string filename;
  udp::socket socket;
  udp::endpoint endpoint_rx;
  std::ofstream output_stream;

  boost::array<char, 128> recv_buf;

  std::list<std::vector<char>*> buffer;
  void handle_data(const boost::system::error_code& error,
                   std::size_t bytes_transferred);
  void receive_data();

  const std::string get_data_file_name();
};

#endif // UDP_CLIENT_HXX

// file: main.cxx
#include "udp_client.hxx"
#include <boost/asio.hpp>
#include <signal.h>
#include <chrono>
#include <boost/thread/thread.hpp>
#include <boost/asio/thread_pool.hpp>
int main()
{
  try
  {
    boost::asio::io_context io;
    udp_client client(io);
    boost::thread t{boost::bind(&boost::asio::io_context::run, &io)};
    io.run();
    t.join();
  }
  catch (std::exception& e)
  {
    std::cout << "erreur" << std::endl;
    std::cerr << e.what() << std::endl;
  }
  return 0;
}

Source: Windows Questions C++

LEAVE A COMMENT