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

问题描述 投票:1回答:2

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

c++ boost-asio
2个回答
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";
    }
}

0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.