2012-06-12 2 views
5

boost::asio::ip::tcp::resolver::resolve()localhostに5秒に1回呼び出す缶詰再生器があります。返されるエンドポイントの数をカウントし、その値を前の繰り返しと比較します。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); 
    } 
} 

サンプルセッション

あなたはそれが、その後、約3.5時間の一方のエンドポイント(127.0.0.1:80)を見つけた見ることができます
~> 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 
~> 

2(127.0.0.1:80と[:: 1] :80)。私は不思議に思っています

  1. なぜエンドポイントの数が1から2に変わるのですか?
  2. 何が原因でしょうか?

ipv4とipv6の両方のアドレスを解決することは意図的なので、ipv4だけに制限したくありません。私はこの動作がasioに固有ではない可能性が高いことを認識しています。同じ動作を直接示すgetaddrinfoを呼び出す再生器もあります。私のプラットフォームはppc64 RHEL 6.2です。私は他の場所での再生を試みていません。

+0

':: 1'アドレスはIPv6ローカルホストアドレスです。 OSがIPv6を有効にしていることを認識するのに時間がかかるかもしれませんか? –

+0

実行中のOSは何ですか? – 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を使用しているようです(これはほとんどの場合使用する必要があります)。このフラグを使用すると、少なくとも1つのグローバルルーティング可能なIPv6アドレスが設定されている場合にのみIPv6アドレスが返されます。おそらくあなたのIPv6接続は常に利用可能ではありませんか?

+0

** Windows固有の警告:** AI_ADDRCONFIGにより、localhostのルックアップが失敗することがあります。詳細については、[Boost ticket 8503](https://svn.boost.org/trac/boost/ticket/8503)を参照してください。 –