是否可以添加多个服务器地址? (Asio,客户端->服务器)
Is it possible to add multiple server adresses? (Asio, Client->Server)
我写了一个小的C++ asio程序,现在我想给客户端的服务器"list"添加一个备份服务器。客户端正在尝试通过 asio 解析器连接到服务器,但如果服务器离线,客户端应该会自动连接到 "backup server"。那么我可以向解析器添加多个地址还是需要编写整个 "try to connect -> fail -> try to connect to next server" 函数?
Asio 不提供这种 "skip and try another server" 功能 out-of-the-box。您需要自己编写该代码。
虽然另一个答案正确地断言你正在寻找的东西完全不存在,你可以很容易构建它:
struct multi_iterator : tcp::resolver::iterator {
using base = typename tcp::resolver::iterator;
multi_iterator() = default;
template <typename T>
explicit multi_iterator(T&& v) : base(std::forward<T>(v)) {}
using base::values_;
void append(tcp::resolver::results_type const& r) {
if (!values_) values_.reset(new typename base::values_type);
values_->insert(values_->end(), r.begin(), r.end());
}
};
现在您可以组合多个查询的结果:
multi_iterator it;
std::vector<tcp::resolver::query> queries {
{ "localhost", "8080" },
{ "localhost", "8081" },
{ "google.com", "https" },
{ "localhost", "6767" },
};
for (auto query : queries)
it.append(tcp::resolver(io).resolve(query));
使用boost::asio::connect
或boost::asio::async_connect
进行端点迭代:
tcp::socket sock(io);
auto ep = *boost::asio::connect(sock, it);
std::cout << "Connected to " << ep.endpoint() << " (for " << ep.host_name() << ":" << ep.service_name() << ")\n";
在我的系统上打印
Connected to 172.217.19.206:443 (for google.com:https)
因为我没有在本地侦听端口 8080 或 8081。打开其中一个后 netcat -l -p 8081
:
Connected to 127.0.0.1:8081 (for localhost:8081)
完整演示
还包括更通用的 basic_multi_iterator<Protocol>
:
#include <boost/asio.hpp>
#include <iostream>
template <typename Proto>
struct basic_multi_iterator : boost::asio::ip::basic_resolver<Proto>::iterator {
using resolver = typename boost::asio::ip::basic_resolver<Proto>;
using base = typename resolver::iterator;
basic_multi_iterator() = default;
template <typename T> explicit basic_multi_iterator(T&& v)
: base(std::forward<T>(v))
{}
using base::values_;
void append(typename resolver::results_type const& r) {
if (!values_)
values_.reset(new typename base::values_type);
values_->insert(values_->end(), r.begin(), r.end());
}
};
using boost::asio::ip::tcp;
using multi_iterator = basic_multi_iterator<tcp>;
int main() {
boost::asio::io_context io;
multi_iterator it;
std::vector<tcp::resolver::query> queries {
{ "localhost", "8080" },
{ "localhost", "8081" },
{ "google.com", "https" },
{ "localhost", "6767" },
};
for (auto query : queries)
it.append(tcp::resolver(io).resolve(query));
try {
tcp::socket sock(io);
auto ep = *boost::asio::connect(sock, it);
std::cout << "Connected to " << ep.endpoint() << " (for " << ep.host_name() << ":" << ep.service_name() << ")\n";
} catch (boost::system::system_error const& e) {
std::cout << e.what() << " - " << e.code().message() << "\n";
}
}
我写了一个小的C++ asio程序,现在我想给客户端的服务器"list"添加一个备份服务器。客户端正在尝试通过 asio 解析器连接到服务器,但如果服务器离线,客户端应该会自动连接到 "backup server"。那么我可以向解析器添加多个地址还是需要编写整个 "try to connect -> fail -> try to connect to next server" 函数?
Asio 不提供这种 "skip and try another server" 功能 out-of-the-box。您需要自己编写该代码。
虽然另一个答案正确地断言你正在寻找的东西完全不存在,你可以很容易构建它:
struct multi_iterator : tcp::resolver::iterator {
using base = typename tcp::resolver::iterator;
multi_iterator() = default;
template <typename T>
explicit multi_iterator(T&& v) : base(std::forward<T>(v)) {}
using base::values_;
void append(tcp::resolver::results_type const& r) {
if (!values_) values_.reset(new typename base::values_type);
values_->insert(values_->end(), r.begin(), r.end());
}
};
现在您可以组合多个查询的结果:
multi_iterator it;
std::vector<tcp::resolver::query> queries {
{ "localhost", "8080" },
{ "localhost", "8081" },
{ "google.com", "https" },
{ "localhost", "6767" },
};
for (auto query : queries)
it.append(tcp::resolver(io).resolve(query));
使用boost::asio::connect
或boost::asio::async_connect
进行端点迭代:
tcp::socket sock(io);
auto ep = *boost::asio::connect(sock, it);
std::cout << "Connected to " << ep.endpoint() << " (for " << ep.host_name() << ":" << ep.service_name() << ")\n";
在我的系统上打印
Connected to 172.217.19.206:443 (for google.com:https)
因为我没有在本地侦听端口 8080 或 8081。打开其中一个后 netcat -l -p 8081
:
Connected to 127.0.0.1:8081 (for localhost:8081)
完整演示
还包括更通用的 basic_multi_iterator<Protocol>
:
#include <boost/asio.hpp>
#include <iostream>
template <typename Proto>
struct basic_multi_iterator : boost::asio::ip::basic_resolver<Proto>::iterator {
using resolver = typename boost::asio::ip::basic_resolver<Proto>;
using base = typename resolver::iterator;
basic_multi_iterator() = default;
template <typename T> explicit basic_multi_iterator(T&& v)
: base(std::forward<T>(v))
{}
using base::values_;
void append(typename resolver::results_type const& r) {
if (!values_)
values_.reset(new typename base::values_type);
values_->insert(values_->end(), r.begin(), r.end());
}
};
using boost::asio::ip::tcp;
using multi_iterator = basic_multi_iterator<tcp>;
int main() {
boost::asio::io_context io;
multi_iterator it;
std::vector<tcp::resolver::query> queries {
{ "localhost", "8080" },
{ "localhost", "8081" },
{ "google.com", "https" },
{ "localhost", "6767" },
};
for (auto query : queries)
it.append(tcp::resolver(io).resolve(query));
try {
tcp::socket sock(io);
auto ep = *boost::asio::connect(sock, it);
std::cout << "Connected to " << ep.endpoint() << " (for " << ep.host_name() << ":" << ep.service_name() << ")\n";
} catch (boost::system::system_error const& e) {
std::cout << e.what() << " - " << e.code().message() << "\n";
}
}