Ускорить связь один ко многим

Я пытаюсь разработать внутренний сканер для нашей инфраструктуры, и я начал изучать boost asio для запуска соединения 254 в то время.

Я не нашел ни одного примера в документации по boost asio, который бы указывал мне правильное направление.

Я хотел бы создать 254 экземпляра объекта, каждый из которых подключался бы и читал, используя async_read_until, используя io_service.

Каков был бы правильный подход для использования нескольких tcp::resolver и нескольких tcp::socket от boost (в идеале по одному на класс?)

Также я вижу некоторые жалобы на резольвер и сокет

У меня очень простой код, и я не очень уверен, куда идти дальше... Буду признателен за любые замечания. Благодарю.

main.cpp:

#include <cstdlib>
#include <iostream>
#include <vector>
#include <thread>

#include <boost/asio.hpp>

#include "Harvester.hpp"

int main(int argc, char* argv[]) {

    if (argc != 2) {
        std::cerr << "Usage: harvest <range> IE: 10.30.0" << std::endl;
        return EXIT_FAILURE;
    }

    boost::asio::io_service io_service;

    // Launch the io_service thread ...
    std::thread t([&io_service]() { io_service.run(); });

    // do a bunch of stuff
    std::string range(argv[1]);
    std::cout << "Range is " << range << std::endl;
    // Build up a list of harvester
    std::string tempRange;

    std::vector<Harvester> harvesters;
    //harvesters.reserve(254);

    for (int x=1; x<255; x++) {
        tempRange = range + "." + std::to_string(x);
        std::cout << "Going to harvest " << tempRange << std::endl;
        harvesters.emplace_back( io_service );
    }
    t.join();
    return EXIT_SUCCESS;
}

harvester.hpp:

#include <boost/asio.hpp>
#include <string>

using boost::asio::ip::tcp;

class Harvester {
    public:
        Harvester(boost::asio::io_service &io_service);
        Harvester(const Harvester&&); // move constructor..
        void connectTo(std::string &ip);
        void doRead();
        void closeConnection();
    private:
        std::string receivedData;
        boost::asio::io_service &io_service_;
        //tcp::resolver resolver;
        tcp::socket socket_;
};

Harvester.cpp

#include "Harvester.hpp"

Harvester::Harvester(boost::asio::io_service &io_service) : io_service_(io_service), socket_(io_service) {

}

// This is for the emplace_back? Create a new object and move into the vector (this break everything big time)
Harvester::Harvester(const Harvester&& other) {
    io_service_ = other.io_service_;
    socket_ = other.socket_;
}

void Harvester::connectTo(std::string &ip) {

}

1 ответ

Без лишних деталей я бы сделал следующее:

За Harvester

class Harvester : public std::enable_shared_from_this<Harvester> {
 public:
  ~Sender() = default;

  template<typename... Args>
  static std::shared_ptr<Harvester> Create(Args&&... args) {
    return std::shared_ptr<Harvester>(new Harvester(std::forward<Args>(args)...));
  }

  void ConnectTo(const std::string& ip_address) {
    ...
    socket_.async_connect(
        endpoint,
        [self = shared_from_this()]
        (const boost::system::error_code&, size_t) {
          // possibly write/read?
        });
  }

  void DoRead() {
    ...
    socket_.async_receive(
        read_buffer_,
        [self = shared_from_this()]
        (const boost::system::error_code&, size_t) {
          // data handling
        });
  }

  void CloseConnection() {
    boost::system::error_code ec;
    socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
    socket_.close(ec);
  }

 private:
  Harvester(boost::asio::io_service& io_service) : socket_(io_service) {}
  Harvester(const Harvester&) = delete;
  Harvester(Harvester&&) = delete;
  Harvester& operator=(const Harvester&) = delete;
  Harvester& operator=(Harvester&&) = delete;

  SocketType socket_;
  MutableBuffer read_buffer_;
}

За main (пропуская ли это поток или просто асинхронный)

...
std::vector<Harvester> harvesters;
harvesters.reserve(254);
for (int i = 0; i < 254; ++i) {
  ...
  auto harvester = Harvester::Create(io_service);
  harvester->ConnectTo(...);  // or however you want to trigger the action
  harvesters.emplace_back(std::move(harvester));
}
...
for (const auto& harvester : harvesters)  // unless you've handled it already
  harvester->CloseConnection();
...

Не беспокойтесь о подвижности, пока не поймете, что скрыто под ним. Сокет, например, является дескриптором. Хотите скопировать его на ходу или просто

Socket(Socket&& other) : sd_(other.sd_) { other.sd_ = -1; }

все зависит от того, чего вы пытаетесь достичь.

Сноска: Для emplace_back чтобы работать как задумано, конструктор перемещения объекта должен быть объявлен noexcept,

Другие вопросы по тегам