Java Tips:マシンのIPアドレスを知るには?
Javaはネットワークに強い言語として知られています。関連するクラスが豊富に提供されていることがその理由の1つとして挙げられますが、その基本である「IPアドレス」を取得する方法を紹介します。
意外とややこしいIPアドレスの取得
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
ネットワークプログラミングをするとき,IPアドレスは随所に必要になります。最近でこそIPアドレスを直接意識するケースは減りましたが,それでも設定やメッセージに必ず登場します。プログラムから自分のIPアドレスを取得するにはどうすればよいでしょうか。今回は,この方法を紹介しましょう。
自ホストのIPアドレスを取得する目的には,ソケットオブジェクトからgetInetAddressメソッドを呼び出したり,java.net.InetAddressクラスのgetLocalHostメソッドで取得するという方法があります。これらは,比較的古くからある手法です。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
しかし,この方法には特殊なマシン構成のときに,思いどおりのIPアドレスができるとは限らないという問題がありました。
通常のクライアントマシンの場合,(127.0.01以外の)IPアドレスは1つしか持たないことも多いですが,構成によっては複数のネットワークインタフェースカード(Network Interface Card,以下NIC),さらに1枚のNICに複数のIPアドレスを割り当てることが可能です。このような構成の場合,前述の方法ではどのIPアドレスを取得できているのかわかりません。
マシンが持つIPアドレスを取得するには,このような機器構成の柔軟さも考慮に入れなくてはならないのです。
Step1) システムは「ネットワークインタフェース」を持つ
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
J2SE 1.4では,java.net.NetworkInterfaceクラスが導入されたことにより,複雑な機器構成のマシンでも柔軟にIPアドレスが取得できるようになりました。このクラスはあくまでも抽象的に「NIC」を表現します。
NetworkInterface.getNetworkInterfaces()とすることでEnumerationが取得できます。このEnumerationを用いると,NetworkInterfaceクラスのインスタンスを列挙できます。そのため,次のようにすると全NetworkInterfaceをループで列挙できます。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
ただし,NICを持たない環境の場合,getNetworkInterfacesメソッドはnullを返しますので注意してください。また,NICは,物理的に装着したものだけでなく,ループバックインタフェース(127.0.0.1,localhostとして利用する)のような論理的なものも認識します。
Step2) NICはIPアドレスを持つ
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
得られたNetworkInterfaceはNICを表現しますが,1つのNICが複数のIPアドレスを持つことがありますので,IPアドレスはあらためて列挙する必要があります。このループにもEnumerationを利用します。先の処理で得たNetworkInterfaceがniという変数とすると,次のようになります。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
このとき,InetAddressの実体はサブクラスであるjava.net.Inet4Addressが返されるのが一般的でしょう。この2重ループにより,全インタフェースの全IPアドレスを取得できます。
2重ループで全部列挙
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
まとめると,次のようになるでしょう。次の例は,自ホストのIPアドレスをすべて列挙して,表示可能な情報を出力するサンプルです。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
意外な落とし穴
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
ところで,Windows XP環境でこのコードを実行させてみると,ni.getDisplayName()の結果が次のように文字化けすることがあります。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
おそらく,システムに問い合わせる段階で直接表示に適さない内部情報を取得してきているのでしょう。そこで,試しにgetDisplayNameメソッドの戻り値を表示する部分を次のように変更して実行すると,なにやら意味のありそうな表示に変わります。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
次の結果を見ると,「パケット スケジューラ ミニポート」という文字が隠されていたようです。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
しかし,なぜここでエンコーディングの変換が必要かという疑問は拭えません。仕様かもしれませんし不具合かもしれません。getDisplayNameを使うよりgetNameのほうが表示には無難なのかもしれないと考えると,奇妙な話です。ちなみに,動作確認はJ2SEのバージョン「1.4.2_05」で行いました。
このTipsの実用的な利用方法としては,getNameメソッドが返す「インタフェース名」を設定ファイルで記述することでコントロールするなどでしょう。または,Swingアプリケーションなどで,NICを選択するダイアログボックスを表示させてもよいでしょう。
「JAVA Developer」より毎週役立つJava Tipsを配信中。ほかにも参考になるTipsは、JAVA Developerサイトのバックナンバーから探すことが可能です。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
Copyright(C) 2010 SOFTBANK Creative Inc. All Right Reserved.