Как запустить несколько приемников, используя boost.thread каждый поток должен быть выделен для каждого приемника? - PullRequest
0 голосов
/ 21 сентября 2019
#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;
}    

Я обновил всю программу.Этот код работает нормально, но не может поместить код потоков в цикл.Я могу создать несколько получателей (потоков) вручную, но мне не удалось создать несколько потоков с помощью цикла.

Я обновил всю программу.Этот код работает нормально, но не может поместить код потоков в цикл.Я могу создать несколько получателей (потоков) вручную, но мне не удалось создать несколько потоков с помощью цикла.

1 Ответ

0 голосов
/ 21 сентября 2019

Вы не показывали receiver класс, я думаю, это выглядит как

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

    }

    boost::asio::io_service& io;
};

, ключевой момент здесь в том, что receiver хранит ссылку на io_service объект.io_service - это один из многих классов в asio, который нельзя скопировать / переместить.Если класс содержит ссылку, то компилятор не может генерировать операции копирования / перемещения для этого типа класса.Также receiver не имеет конструктора по умолчанию.Эти ограничения приводят к тому, что вы не можете использовать, например, vector<receiver> для хранения получателей - что будет полезно, когда объекты создаются в цикле.

Простым способом решения этой проблемы является использование (умных) указателей - 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";
  }

Скомпилировано

...