Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Boost.Asio解析器的结果不同_C++_Sockets_Boost_Boost Asio_Getaddrinfo - Fatal编程技术网

C++ Boost.Asio解析器的结果不同

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]

我有一个罐装复制器,每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 );
    }
}
您可以看到它在大约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(),主机,服务)

    我不是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);