繁体   English   中英

Boost.Asio 解析器的结果不同

[英]results from Boost.Asio resolver differ

我有一个罐头复制boost::asio::ip::tcp::resolver::resolve() ,每 5 秒在localhost上调用boost::asio::ip::tcp::resolver::resolve()一次。 它计算返回的端点数,并将该值与前一次迭代进行比较。

#include <boost/asio.hpp>

#include <iostream>

int main(int argc, char *argv[])
{
    if ( argc < 3 ) {
        std::cerr << argv[0] << " host port" << std::endl;
        exit( EXIT_FAILURE );
    }
    const char* host = argv[1];
    const char* service = argv[2];

    boost::asio::io_service io_service;
    boost::asio::ip::tcp::resolver resolver( io_service );

    size_t previous = 0;
    while ( true ) {
        boost::asio::ip::tcp::resolver::iterator i(
                resolver.resolve(
                    boost::asio::ip::tcp::resolver::query( host, service )
                    )
                );
        size_t count( 0 );
        while ( i != boost::asio::ip::tcp::resolver::iterator() ) {
            std::cout << i->endpoint() << std::endl;
            ++i;
            ++count;
        }

        std::cout << "got " << count << " addresses" << std::endl;
        if ( previous == 0 ) {
            previous = count;
        }
        assert( count == previous );

        sleep( 5 );
    }
}

示例会话

~> time ./addrinfo_asio localhost 80

...

127.0.0.1:80
got 1 addresses
[::1]:80
127.0.0.1:80
got 2 addresses
addrinfo_asio: addrinfo_asio.cc:35: int main(int, char**): Assertion `count == previous' failed.
Aborted (core dumped)

real    216m20.515s
user    0m0.181s
sys     0m0.193s
~> 

您可以看到它在大约 3.5 小时内找到了一个端点 (127.0.0.1:80),然后找到了两个端点(127.0.0.1:80 和 [::1]:80)。 我在想

  1. 为什么端点计数从一变为二?
  2. 什么可能导致它?

解析 ipv4 和 ipv6 地址是有意的,我不想将查询限制为仅 ipv4。 我意识到这种行为可能不是 asio 特有的,我也有一个直接调用getaddrinfo的复制器,它表现出相同的行为。 如果相关,我的平台是 ppc64 RHEL 6.2。 我没有尝试在其他地方复制。

您只能将解析器限制为 IPv4:
ip::tcp::resolver::query(ip::tcp::v4(), 主机, 服务)

如果您查看 Chris Kohlhoff(asio 的作者) 在 boost con 2011 上关于 ipv6 和 asio 的演示,他会执行以下技巧。

他对端点列表重新排序,因此 ipv4 端点在列表中排在第一位,并带有注释“现实检查:IPv6 不太可能可用”。

他的示例代码在 boost 1.47 中发布的 asio 版本中有效,但在我使用的版本(asio standalone 1.18.0)中不再有效,因为他习惯于随着 C++ 的发展不断改变 asio 实现。

无论如何,以下代码适用于包含在 boost 1.74 中的 asio 1.18.0

auto resolverResults(mResolver.resolve(hostName, serviceName));
std::transform(resolverResults.begin(), resolverResults.end(), std::back_inserter(endpoints), [](const asio::ip::basic_resolver_entry<asio::ip::tcp>& entry) { return entry.endpoint(); });
std::stable_partition(endpoints.begin(), endpoints.end(), [](const asio::ip::tcp::endpoint& endpoint) { return endpoint.protocol() == asio::ip::tcp::v4(); });
auto endpointsWithIP4First = asio::ip::tcp::resolver::results_type::create(endpoints.begin(), endpoints.end(), hostName, serviceName);

好吧,我不是 boost 专家,但快速浏览告诉我它似乎在默认情况下使用AI_ADDRCONFIG (这很好,几乎应该总是使用它)。 如果您至少配置了一个全局可路由的 IPv6 地址,则使用该标志它只会返回 IPv6 地址。 也许您的 IPv6 连接并不总是可用?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM