1

getaddrinfoandを使用してホスト名情報を決定し、失敗した場合はandgetnameinfoにフォールバックする古いコードを調べています。gethostnamegethostbynamegetnameinfo

さて、これは私には間違っているようです。推奨事項を作成できるように、コードの意図を理解しようとしています。長くて複雑なので、コード全体をここに再投稿したくはありませんが、要約してみます。

私が知る限り、このコードのポイントは、リッスンしているソケットに接続するために別のプロセスで使用できる文字列を生成することです。これは、ローカル プロセスだけでなく、リモート ホストがこのコンピュータに接続し直すためのものでもあるようです。

したがって、問題のコードは基本的に次のことを行っています。

  • getaddrinfo(node = NULL, service = port, hints.ai_flags = AI_PASSIVE, ai);socket()-- これは、で使用できるの可能な引数のリストを取得しbind()ます。
  • 結果のリストを調べて、ソケットを作成します。
  • 初めてソケットが正常に作成されたとき、これは「使用済み」として選択されaddrinfoます。
  • ai_addr選択したのaddrinfoを呼び出しgetnameinfo()て、関連するホスト名を取得します。
  • これが失敗した場合は、 を呼び出して、結果gethostname()を調べますgethostbyname()

これが間違っていると思う理由はいくつかありますが、私の論理を検証したいと思います。まず、いくつかの実験から、getnameinfo()ここではほぼ常に失敗しているようです。入力アドレスは宛先ではなくリッスン ソケットであるため、不明であると思われます。この観点からは、有効な IP は必要ありません。次に、結果を呼び出しgethostname()て渡すと、ほとんどの場合、それ自体gethostbyname()と同じ結果が返さgethostname()れます。つまり、ローカル ホスト名を確認しているだけで、私には無意味に思えます。これは、必ずしもリモート ホストで使用できるとは限らないため、問題がありますね。

どういうわけか、サブネット上の自分のホスト名を特定しようとする全体的な考えはそれほど役に立たない可能性があると思いますが、別のホストにメッセージを ping して、ホストがどの IP アドレスを認識しているかを確認する必要があります。(残念ながら、このコンテキストでは意味がありません。プログラムのこのレベルで他のピアを知らないためです。)たとえば、ローカルホストには複数のNICがあり、したがって複数のIPアドレスがある可能性があるため、特定しようとしています単一のホストとアドレスのペアは無意味です。(すべての結果bind()を同時にリッスンするのが正しい解決策ですか?) addrinfo

また、名前を に渡してフラグgetaddrinfo()を設定するだけで名前を解決できることにも気付きました。つまり、ステップが冗長になる可能性があります。ただし、アプリオリにホスト名を提供せずに、ホスト名のある種の公平なビューを決定しようとしているため、ここではこれが行われていないと思います。もちろん、それは失敗し、とにかく使用することになります! また、「localhost」を に提供しようとしましたが、Linux ではホスト名が ai_canonname` に報告されますが、OS X では「localhost」になるだけなので、これはクロスプラットフォームであると想定されているため、あまり役に立ちません。AI_CANONNAMEgetnameinfo()gethostname()getaddrinfo()

要約すると、私の質問は、最新のソケットプログラミングで、サブネットピアにアナウンスできるローカルホスト名を取得する正しい方法が存在する場合、どうすればよいですか? このコードを単純に の結果を返すように置き換えることに傾いていますがgethostname()、 のような最新の呼び出しを使用したより適切な解決策があるかどうか疑問に思っていますgetaddrinfo()

これを行う方法がないと答えた場合は、gethostname()ここで何かを返す必要があるため、とにかく使用する必要があります。そうしないと、API が壊れてしまいます。

4

2 に答える 2

1

これを正しく読めば、ローカル ソケットの作成とリモート ホストの再接続に成功する可能性が高い非 localhost ソケット アドレスを取得するだけで済みます。

「GetBestAddressForSocketBind」という参照できる関数を作成しました。こちらの GitHub プロジェクト ページから入手できます。親ディレクトリの一部のコードを参照する必要がある場合があります。

このコードは基本的に、getifaddrsを使用してアダプタを列挙し、ループバック/ローカルではなく「稼働中」で、目的のアドレス ファミリ (AF_INET または AF_INET6) の IP アドレスを持つ最初のアダプタを選択します。

お役に立てれば。

于 2012-09-05T04:08:32.733 に答える
1

IPv6 プログラミングに関するUlrich Drepper の記事を参照する必要があると思います。それは比較的短く、あなたの懸念のいくつかに答えるかもしれません. 本当に便利だと思いました。(少なくとも) 疑似コードなしで質問に答えるのは非常に難しいため、このリンクを投稿しています。

于 2012-09-05T03:28:40.870 に答える