【问题标题】:How to run multiple receiver using boost.thread each thread should be allocated for each receiver?如何使用 boost.thread 运行多个接收器每个线程应该为每个接收器分配?
【发布时间】:2020-01-22 03:49:05
【问题描述】:
#include <iostream>
#include <time.h>
#include <chrono>
#include <ctime>
#include <string>
#include <boost/asio.hpp>
#include "boost/bind.hpp"
#include <string>
#include <bits/stdc++.h> 
#include <thread>
#include <boost/thread.hpp>
using namespace std; 
using boost::asio::io_service;


const short multicast_port = 30001;

class receiver
{
public:
  receiver(boost::asio::io_service& io_service,
      const boost::asio::ip::address& listen_address,
      const boost::asio::ip::address& multicast_address)
     : socket_(io_service)

  {
    // Create the socket so that multiple may be bound to the same address.
    boost::asio::ip::udp::endpoint listen_endpoint(
    listen_address, multicast_port);
    socket_.open(listen_endpoint.protocol());
    socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
    socket_.bind(listen_endpoint);

    // Join the multicast group.
    socket_.set_option(
        boost::asio::ip::multicast::join_group(multicast_address));

    socket_.async_receive_from(
        boost::asio::buffer(data_, max_length), sender_endpoint_,
        boost::bind(&receiver::handle_receive_from, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive_from(const boost::system::error_code& error,
      size_t bytes_recvd)
  {
    if (!error)
    {
      std::cout.write(data_, bytes_recvd);

      std::chrono::time_point< std::chrono::system_clock > now = std::chrono::system_clock::now();
      auto duration = now.time_since_epoch();
      auto nanoseconds = std::chrono::duration_cast< std::chrono::nanoseconds >( duration );
      std::cout<<" "<<boost::this_thread::get_id()<<" "<<nanoseconds.count() << " nanoseconds "<<std::endl;



      socket_.async_receive_from(
          boost::asio::buffer(data_, max_length), sender_endpoint_,
          boost::bind(&receiver::handle_receive_from, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
  }

private:
  boost::asio::ip::udp::socket socket_;
  boost::asio::ip::udp::endpoint sender_endpoint_;
  enum { max_length = 1024 };
  char data_[max_length];
};

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 3)
    {
      std::cerr << "Usage: receiver <listen_address> <multicast_address>\n";
      std::cerr << "  For IPv4, try:\n";
      std::cerr << "    receiver 0.0.0.0 239.255.0.1\n";
      std::cerr << "  For IPv6, try:\n";
      std::cerr << "    receiver 0::0 ff31::8000:1234\n";
      return 1;
    }

    boost::asio::io_service io_service,io_service1;

        receiver r(io_service,
        boost::asio::ip::address::from_string(argv[1]),
        boost::asio::ip::address::from_string(argv[2]));

        receiver r1(io_service1,
        boost::asio::ip::address::from_string(argv[1]),
        boost::asio::ip::address::from_string(argv[2]));   


    boost::thread thread1{[&io_service](){ io_service.run(); }}; 

    boost::thread thread2{[&io_service1](){ io_service1.run(); }};
    thread1.join();
    thread2.join();

      //  boost::asio::io_service io_service;
      //   receiver r(io_service,
      //   boost::asio::ip::address::from_string(argv[1]),
      //   boost::asio::ip::address::from_string(argv[2]));

    //  for (int i = 0; i < 2; ++i) {
    //     boost::thread z(boost::bind(&boost::asio::io_service::run, &io_service));
    //   z.join();
    // }

  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}    

我已经更新了整个程序。 此代码工作正常,但无法将线程代码放入循环中。 我可以手动创建多个接收器(线程),但无法使用循环创建多个线程。

我已经更新了整个程序。 此代码工作正常,但无法将线程代码放入循环中。 我可以手动创建多个接收器(线程),但无法使用循环创建多个线程。

【问题讨论】:

    标签: c++ multithreading boost boost-asio boost-thread


    【解决方案1】:

    你没有显示receiver类,我猜它看起来像

    struct receiver
    {
        receiver(boost::asio::io_service& io, ...)
        : io(io), ... 
        {
    
        }
    
        boost::asio::io_service& io;
    };
    

    这里的关键点是receiver 存储对io_service 对象的引用。 io_service 是 asio 中许多无法复制/移动的类之一。如果类包含引用,则编译器无法为该类生成复制/移动操作。 receiver 也没有默认构造函数。这些限制导致您不能使用例如vector&lt;receiver&gt; 来存储接收器 - 在循环中创建对象时会有用。

    解决此问题的简单方法是使用 (smart) 指针 - shared_ptr

    如果io_service没有在你的receiver实例之间共享,你可以把它作为receiver的成员变量:

    struct receiver {
        receiver(boost::asio::ip::address, boost::asio::ip::address)
        : th(boost::bind(&boost::asio::io_service::run,&ioService))
        {     // ^^^ thread is started here
    
        }
    
        ~receiver() {
            if (th.joinable())
                th.join();
        }
        boost::asio::io_service ioService;
        boost::thread th;
    };
    

    main 可以简化为:

      try {
        if (argc != 3) {
          std::cerr << "Usage: receiver <listen_address> <multicast_address>\n";
          std::cerr << "  For IPv4, try:\n";
          std::cerr << "    receiver 0.0.0.0 239.255.0.1\n";
          std::cerr << "  For IPv6, try:\n";
          std::cerr << "    receiver 0::0 ff31::8000:1234\n";
          return 1;
        }
    
        std::vector<boost::shared_ptr<receiver>> receivers;
        for (int i = 0; i < 2; ++i) 
        {
            receivers.push_back(boost::make_shared<receiver>(boost::asio::ip::address::from_string(argv[1]),
              boost::asio::ip::address::from_string(argv[2])));
        }
      }
      catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << "\n";
      }
    

    Compiled

    【讨论】:

    • 非常感谢您的回答,但我在 (: th(boost::bind(&boost::asio::io_service::run,&ioService))) 这一行中仍然遇到小问题用于编译程序。现在我已经编辑了一个完整的程序,包括接收器类。如果你能根据这个程序建议你之前的更改,那对我很有帮助..
    • 如果你有编译错误,你应该把它放在你的问题上。没有这个,就很难判断出了什么问题。 io_service::run 是重载的成员函数,因此可能需要强制转换:&amp;boost::asio::io_service::run
    猜你喜欢
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2016-03-02
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多