是否可以添加多个服务器地址? (Asio,Client-> Server)

时间:2018-03-01 00:51:47

标签: c++ boost-asio

我写了一个小的C ++ asio程序,现在我想将备份服务器添加到客户端的服务器“列表”中。客户端尝试通过asio解析程序连接到服务器,但如果服务器处于脱机状态,客户端应自动连接到“备份服务器”。那么我可以向解析器添加多个地址,还是需要编写整个“尝试连接 - >失败 - >尝试连接到下一个服务器”功能?

2 个答案:

答案 0 :(得分:3)

虽然正确的其他答案断言您正在寻找完全的东西不存在,但您可以非常轻松地构建它:

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::connectboost::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";
    }
}

答案 1 :(得分:0)

Asio不提供这种“跳过并尝试其他服务器”功能的开箱即用功能。您需要自己编写该代码。