Im trying to develop an internal scanner for our infrastructure and I have started looking into boost asio to launch 254 connection at the time.
我正在尝试为我们的基础设施开发内部扫描仪,我已经开始考虑使用boost asio来启动254连接。
I havent found any example in boost asio documentation that would point me in the right direction.
我没有在boost asio文档中找到任何可以指向正确方向的示例。
I would like to create 254 instances of an object that would each connect and read using async_read_until, using the io_service.
我想使用io_service创建254个对象实例,每个对象使用async_read_until进行连接和读取。
What would be a correct approach to use multiple tcp::resolver and multiple tcp::socket from boost (idealy one per class?)
从boost中使用多个tcp :: resolver和多个tcp :: socket的正确方法是什么(理想每个类一个?)
Also i see some complaints about resolver and socket not movable
我也看到一些关于旋转变压器和插座不能移动的投诉
I have very basic code and not too sure where to head next... I would appreciate any inputs. Thanks.
我有非常基本的代码,不太确定下一步要去哪里...我会很感激任何输入。谢谢。
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 个解决方案
#1
0
Without unnecessary details, the following is what I would do:
没有不必要的细节,以下是我会做的:
For 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_;
}
For main
(leaving out whether threaded or simply asynchronous)
对于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();
...
Don't worry about movability until you understand what is hidden underneath. A socket, for example, is a descriptor. Would you want to duplicate it on a move, or simply
在了解隐藏在下面的内容之前,不要担心可移动性。例如,套接字是描述符。您想要在移动中复制它,还是简单地复制它
Socket(Socket&& other) : sd_(other.sd_) { other.sd_ = -1; }
all depends on what you try to achieve.
一切都取决于你想要达到的目标。
Footnote: For emplace_back
to work as intended, the object's move constructor needs to be declared noexcept
.
脚注:为了使emplace_back按预期工作,需要将对象的移动构造函数声明为noexcept。
#1
0
Without unnecessary details, the following is what I would do:
没有不必要的细节,以下是我会做的:
For 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_;
}
For main
(leaving out whether threaded or simply asynchronous)
对于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();
...
Don't worry about movability until you understand what is hidden underneath. A socket, for example, is a descriptor. Would you want to duplicate it on a move, or simply
在了解隐藏在下面的内容之前,不要担心可移动性。例如,套接字是描述符。您想要在移动中复制它,还是简单地复制它
Socket(Socket&& other) : sd_(other.sd_) { other.sd_ = -1; }
all depends on what you try to achieve.
一切都取决于你想要达到的目标。
Footnote: For emplace_back
to work as intended, the object's move constructor needs to be declared noexcept
.
脚注:为了使emplace_back按预期工作,需要将对象的移动构造函数声明为noexcept。