System.Net.Dns.GetHostEntryを使った名前解決の問題

  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存

.NET 2.0 以降でホスト名の名前解決を行うには System.Net.Dns クラスにある GetHostEntry メソッドを用いる。(自分のマシンのIPアドレスを取得する方法は ローカルマシンのIPv4アドレスを取得する を参照)

パラメータにホスト名を渡すとDNSサーバーにクエリが送られ、AddressListプロパティにIPアドレスのリストが格納される(ホスト名とIPアドレスは1対1とは限らない)。通常は最初のアドレスを使えばよいので、下記のようにすれば、ホスト名からIPアドレスを得られる。

では、このhostにIPアドレスを渡したらどうなるだろう?

普通はそのままのIPアドレスを返してほしいところだ。つまり、下記のようなコードを書けば、addressには”192.168.1.3″が返ってほしいわけである。

実際、このメソッドはこういう仕様になっていて、上のコードではaddressに”192.168.1.3″が返るようになっている。

ただし、一つ問題がある。これがうまくいくのは同セグメントかつ、DNS サーバーが適切に設定されている場合のみである。

つまり、実行したパソコンの IP アドレスが192.168.1.1/24 だとして、GetHostEntryメソッドに渡すアドレスが192.168.1.3/24の場合はうまくいくのだが、192.168.2.3/24の場合にはうまくいかない。SocketException例外で”そのようなホストは存在しません。”と言われる。

おそらく別セグメントの場合はDNSサーバーに問い合わせに行くのだが、DNSサーバーが名前解決をできずに例外となるのだろう。なお、この問題は192.168.2.3がDNSサーバーに登録されている場合は発生しない。また、この症状が見られるのはVista以降のみでXPの場合は発生しなかった。

ともかくも最初に示したコードでは、別セグメントのIPアドレスが渡されたときに通信ができない事態があり得る。これを避けるには下記のようにIPアドレスかどうかを事前に判断してやればよい。

IPAddress.TryParseは渡した文字列をIPAddressクラスのインスタンスに変換するメソッドである(名前解決はしない)。このメソッドはint.TryParseなどと同じように変換の可否をboolで返すので、失敗した場合(ホスト名の場合)は、Dns.GetHostEntryメソッドによって、名前解決してやればよい。

これでaddressには無事、希望のIPアドレスが得られるはずである。

That’s it!

(この記事は移植記事です。)

スポンサーリンク
  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存
スポンサーリンク