我有一个罐装复制品,每5秒钟在boost::asio::ip::tcp::resolver::resolve()
上调用一次localhost
。它计算返回的端点数,并将该值与上一次迭代进行比较。
#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
~>
您可以看到它找到一个端点(127.0.0.1:80)约3.5小时,然后找到两个(127.0.0.1:80和[:: 1]:80)。我想知道
有意解析ipv4和ipv6地址,我不想将查询限制为仅ipv4。我意识到这种行为可能不是特定于asio,我还有一个直接调用getaddrinfo
的再现器,它表现出相同的行为。如果相关,我的平台是ppc64 RHEL 6.2。我没有尝试在别处复制。
答案 0 :(得分:3)
您只能将解析器限制为IPv4:
ip :: tcp :: resolver :: query(ip :: tcp :: v4(),host,service)
答案 1 :(得分:1)
嗯,我不是助推专家,但快速浏览告诉我默认情况下似乎正在使用AI_ADDRCONFIG
(这很好,几乎应该总是使用它)。使用该标志,如果您配置了至少一个全局可路由IPv6地址,它将仅返回IPv6地址。也许您的IPv6连接并不总是可用?
答案 2 :(得分:1)
如果您看看克里斯·科霍夫(asio的作者)presentation on ipv6 and asio at boost con 2011的话,他会做以下技巧。
他对端点列表进行了重新排序,因此ipv4端点在列表中排名第一,并带有注释“真实性检查:IPv6尚不可用”。
他的示例代码在boost 1.47中发布的asio版本中可用,但是由于他习惯随着C ++的发展不断更改asio实现,因此在我正在使用的版本(asio独立版本1.18.0)中不再起作用。
无论如何,以下代码在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);