提升 asio 异步 udp 客户端,处理程序从未触发

时间:2021-06-10 11:12:58

标签: c++ asynchronous boost udp asio

我已经为此苦苦挣扎了将近 2 周,我认为现在是时候了 寻求帮助。

我需要从在 fpga 上运行的服务器获取数据。服务器已写入 不幸的是,某人不再与我们合作。虽然服务器 按预期工作,因为当我发送请求时,我可以用wireshark看到 预期的内容。 Wireshark 在执行 c++ udp 的计算机上运行 客户。

表格中的前五行 (1..5) 是我发送的。每隔一行, 在 ICMP 之外,由服务器发送。服务器通过多个发送消息 端口根据消息类型。我认为发送数据正常工作 否则我不会得到第 6 行到 xxx。

问题是我的客户从来没有收到任何东西。处理程序从不 触发,我找不到原因。

你能帮我一个这个吗。

非常感谢您抽出宝贵时间。

奥利维尔

<头>
“不” “来源” “目的地” “协议” “长度” “信息” “端口”
“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” “目标不可达(通信管理过滤)” “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” “目标不可达(通信管理过滤)” “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” “目标不可达(通信管理过滤)” “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” “目标不可达(通信管理过滤)” “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” “目标不可达(通信管理过滤)” “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” “目标不可达(通信管理过滤)” “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;
}

2 个答案:

答案 0 :(得分:0)

查看 UDP 响应表(假设您的 C++ 程序运行在 192.168.0.254 上),您可能应该绑定到端口 32776(即 0x8008),例如在start_receive

socket.open(udp::v4());
socket.bind({{}, 0x8008});

使用简单的测试驱动程序对我有用:

netcat -u localhost 32776 -w 0 <<< '01234567'

然后打印例如:

bool udp_client::set_acquisition_and_get_data(std::vector<std::vector<unsigned char> >&) begin
bool udp_client::send_data(std::vector<std::vector<unsigned char> >&)
send data
void udp_client::start_receive()
socket opened: true
async receive from started
void udp_client::start_receive() socket data started
void udp_client::handle_data(const boost::system::error_code&, std::size_t)
socket opened: true
async receive from started
void udp_client::handle_data(const boost::system::error_code&, std::size_t)
socket opened: true
async receive from started
...

等等。此外,data.dat 文件还包含:

00000000: 3031 3233 3435 3637 0a30 3132 3334 3536  01234567.0123456
00000010: 370a                                     7.

答案 1 :(得分:0)

我很抱歉...这只是一个防火墙问题... 我将连接从公共区域切换到受信任区域,现在,我收到了数据。至少当客户端独立运行时(简单的 udp_client + main)。 当我尝试在 qt 应用程序中运行它时,它不会触发句柄。

相关问题