2012-06-12 32 views
5

我有一個罐頭播放器,每5秒調用boost::asio::ip::tcp::resolver::resolve()localhost一次。它計算返回的端點數並將該值與前一次迭代進行比較。來自Boost.Asio解析器的結果不同

#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)。我想知道

  1. 爲什麼端點數從一個變到兩個?
  2. 什麼可能導致它?

解決ipv4和ipv6地址是故意的,我不想限制查詢只是ipv4。我意識到這種行爲可能不是特定於asio,我也有一個直接調用getaddrinfo的播放器,它表現出相同的行爲。如果這是相關的,我的平臺是ppc64 RHEL 6.2。我沒有嘗試在其他地方複製。

+0

「:: 1」地址是IPv6本地主機地址。也許OS需要很長時間才能意識到它啓用了IPv6? –

+0

你正在使用的操作系統是什麼? – gda2004

+0

@ gda2004查看問題的最後一句話,ppc64 RHEL 6.2 –

回答

3

可以限制解析器僅支持IPv4:
IP :: TCP ::解析器::查詢(IP :: TCP :: V4(),主機服務)

+1

AFAIU的問題不是如何限制getaddrinfo返回的地址,但爲什麼IPv6地址在一段時間過去後顯示。 – Ralf

+0

好吧,我的印象是,主題啓動器不知道他的解析器查詢包含ipv4和ipv6,所以他得到*不受歡迎的* ipv6查詢。另一方面,衆所周知,ipv6 DNS查詢可能會很痛苦...... –

+0

@IgorR。我知道':: 1'地址是'ipv6-localhost',我編輯了我的問題來反映這一點。我不想將我的解決方案查詢限制在ipv4上。 –

1

嗯,我沒有提振專家,但快速瀏覽告訴我,它似乎默認使用AI_ADDRCONFIG(這是好的,它應該幾乎總是使用)。如果您至少配置了一個全局可路由IPv6地址,則該標誌只會返回IPv6地址。也許你的IPv6連接並不總是可用?

+0

**特定於Windows的警告:** AI_ADDRCONFIG可能會導致本地主機查找失敗。有關詳細信息,請參見[Boost票證8503](https://svn.boost.org/trac/boost/ticket/8503)。 –