简体   繁体   English

Boost.Asio 解析器的结果不同

[英]results from Boost.Asio resolver differ

I have a canned reproducer invoking boost::asio::ip::tcp::resolver::resolve() on localhost once every 5 seconds.我有一个罐头复制boost::asio::ip::tcp::resolver::resolve() ,每 5 秒在localhost上调用boost::asio::ip::tcp::resolver::resolve()一次。 It counts the number of endpoints returned and compares that value against the previous iteration.它计算返回的端点数,并将该值与前一次迭代进行比较。

#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 );
    }
}

sample session示例会话

~> 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
~> 

You can see it found one endpoint (127.0.0.1:80) for about 3.5 hours, then found two (127.0.0.1:80 and [::1]:80).您可以看到它在大约 3.5 小时内找到了一个端点 (127.0.0.1:80),然后找到了两个端点(127.0.0.1:80 和 [::1]:80)。 I'm wondering我在想

  1. why the endpoint count changes from one, to two?为什么端点计数从一变为二?
  2. what could cause it?什么可能导致它?

Resolving both ipv4 and ipv6 addresses is intentional, I do not want to limit the query to just ipv4.解析 ipv4 和 ipv6 地址是有意的,我不想将查询限制为仅 ipv4。 I realize this behavior is likely not specific to asio, I also have a reproducer invoking getaddrinfo directly that exhibits the same behavior.我意识到这种行为可能不是 asio 特有的,我也有一个直接调用getaddrinfo的复制器,它表现出相同的行为。 My platform is ppc64 RHEL 6.2 if that is relevant.如果相关,我的平台是 ppc64 RHEL 6.2。 I have not tried reproducing elsewhere.我没有尝试在其他地方复制。

You can limit resolver to IPv4 only:您只能将解析器限制为 IPv4:
ip::tcp::resolver::query(ip::tcp::v4(), host, service) ip::tcp::resolver::query(ip::tcp::v4(), 主机, 服务)

If you take a look at Chris Kohlhoff's (the author of asio) presentation on ipv6 and asio at boost con 2011 , he does the following trick.如果您查看 Chris Kohlhoff(asio 的作者) 在 boost con 2011 上关于 ipv6 和 asio 的演示,他会执行以下技巧。

He reorders the list of endpoints so the ipv4 endpoints come first in the list, with the comment "reality check: IPv6 is unlikely to be available yet".他对端点列表重新排序,因此 ipv4 端点在列表中排在第一位,并带有注释“现实检查:IPv6 不太可能可用”。

His example code works in the version of asio released in boost 1.47, but it no longer works in the version I am using (asio standalone 1.18.0) due to his habit of constantly changing the asio implementation as the C++ evolves.他的示例代码在 boost 1.47 中发布的 asio 版本中有效,但在我使用的版本(asio standalone 1.18.0)中不再有效,因为他习惯于随着 C++ 的发展不断改变 asio 实现。

Anyway, the following code works in asio 1.18.0 which is included in boost 1.74无论如何,以下代码适用于包含在 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);

Well I'm no boost expert, but a quick browse tells me it seems to be using AI_ADDRCONFIG by default (which is good, it should almost always be used).好吧,我不是 boost 专家,但快速浏览告诉我它似乎在默认情况下使用AI_ADDRCONFIG (这很好,几乎应该总是使用它)。 With that flag it will only return IPv6 addresses if you have at least one global routable IPv6 address configured.如果您至少配置了一个全局可路由的 IPv6 地址,则使用该标志它只会返回 IPv6 地址。 Perhaps your IPv6 connection is not always available?也许您的 IPv6 连接并不总是可用?

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

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