C++ Boost.Asio解析器的结果不同
我有一个罐装复制器,每5秒在C++ Boost.Asio解析器的结果不同,c++,sockets,boost,boost-asio,getaddrinfo,C++,Sockets,Boost,Boost Asio,Getaddrinfo,我有一个罐装复制器,每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]
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 );
}
}
您可以看到它在大约3.5小时内找到了一个端点(127.0.0.1:80),然后找到了两个端点(127.0.0.1:80和[::1]:80)。我在想
解析ipv4和ipv6地址是有意的,我不想将查询仅限于ipv4。我意识到这种行为可能不是asio特有的,我还有一个复制程序直接调用
getaddrinfo
,它显示了相同的行为。如果相关的话,我的平台是ppc64 RHEL 6.2。我没有尝试在其他地方复制。您可以将解析器限制为仅限于IPv4:ip::tcp::resolver::query(ip::tcp::v4(),主机,服务)我不是boost专家,但快速浏览告诉我,默认情况下,它似乎在使用
AI_ADDRCONFIG
(这很好,几乎应该总是使用它)。如果您至少配置了一个全局可路由IPv6地址,则该标志将仅返回IPv6地址。也许你的IPv6连接并不总是可用的?如果你看看Chris Kohlhoff(asio的作者),他会做以下的技巧
他对端点列表进行了重新排序,使ipv4端点排在列表的第一位,并给出了“现实检查:IPv6还不太可能可用”的注释
他的示例代码在Boost 1.47中发布的ASIO版本中工作,但它不再适用于我正在使用的版本(ASIO Stutial1.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);
自动解析结果(mResolver.resolve(主机名、服务名));
std::transform(resolverResults.begin()、resolverResults.end()、std::back_插入器(端点),[](const asio::ip::basic_resolver_entry&entry){return entry.endpoint();});
std::stable_分区(endpoints.begin()、endpoints.end()、[](const-asio::ip::tcp::endpoint&endpoint){return-endpoint.protocol()==asio::ip::tcp::v4();});
自动端点Swithip4First=asio::ip::tcp::解析器::结果类型::创建(endpoints.begin()、endpoints.end()、主机名、serviceName);
该::1
地址是IPv6本地主机地址。也许操作系统需要很长时间才能意识到它启用了IPv6?您正在运行的操作系统是什么?@gda2004请参见问题的最后一句,ppc64-RHEL 6。2@SamMiller道歉我错过了@Sam Miller你是在只使用IPv4的网络上吗?我只是在这里抛出我的想法。问题不是如何限制getaddrinfo返回的地址,而是为什么IPv6地址在一段时间后出现。好吧,我的印象是主题启动者不知道他的解析程序查询同时包含ipv4和IPv6,所以他收到了不想要的ipv6查询。另一方面,众所周知,ipv6 DNS查询可能非常慢…@IgorR。我知道::1
地址是ipv6本地主机
,我编辑了我的问题以反映这一点。我不想将我的解析查询仅限于ipv4。非常感谢。即使在我的本地机器上测试连接到另一个本地服务器时,我的连接时间(秒)也非常慢。事实证明,如果我将搜索限制在IPv4上,搜索速度会非常快。这是使用同步升压。我在非常特定的条件下运行代码,所以ipv4和同步对我来说并不重要。也许这会在将来帮助其他人。特定于Windows的警告:AI_ADDRCONFIG可能会导致本地主机的查找失败。有关详细信息,请参阅。
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);