今週も前回に引きつづきjava.netパッケージに関する機能拡張を紹介していきます。

今週紹介するのはネットワークインタフェースに関する情報取得です。

Javaはもともとハードウェアへのアクセスをなるべくさせない方針で開発されてきました。たとえば、Javaから直接メモリやI/Oにアクセスすることは限定されています。しかし、だんだんとその制限も緩んでいるようです。

Java SE 6ではネットワークインタフェースに関する制限が緩くなりました。具体的には、java.net.NetworkInterfaceクラスで情報取得のための新しいメソッドが多数定義されています。

NetworkInterfaceクラスはJ2SE 1.4で導入されたので、比較的新しいクラスです。このクラスは、たとえばUNIXであればle0とかeth0などで表されるネットワークインタフェースを表しています。

J2SE 1.4では、インタフェースのアドレスや名前などを取得することができました。Java SE 6ではこれに加えて、表1に示す情報を取得することができます。

表1 NetworkInterfaceクラスで扱う情報
名称 メソッド名 戻り値の型 補足
アドレス getInterfaceAddresses List
<InterfaceAddress>
アドレス、ブロードキャストアドレスなど
サブインタフェース getSubInterface Enumeration
<NetworkInterface>
 
親インタフェース getParent NetworkInterface このインタフェースがサブインタフェースの場合
起動状態 isUp boolean 起動中であればtrue
ループバック isLookback boolean ループバックインタフェースであればtrue
ポイントツーポイント isPointToPoint boolean モデムでPPP接続などをしている場合はtrue
マルチキャストの可否 supportsMulticast boolean マルチキャストサポートしているかどうか
ハードウェアアドレス getHardwareAddress byte[] 通常はMACアドレスを示す
最大転送単位(MTU) getMTU int  
仮想インタフェース isVirtual boolean 仮想インタフェースであればtrue

getInterfaceAddressesメソッドの戻り値は、新しく導入されたInterfaceAddressクラスが使われています。InterfaceAddressクラスにはアドレスだけでなく、ブロードキャストアドレスおよび接頭辞長も一緒に保持するクラスです。

それでは、サンプルを使ってこれらのメソッドを使ってみましょう。

サンプルのソース NetworkInterfaceSample.java

このサンプルはNetworkInterface#getNetworkInterfacesメソッドを使用して、すべてのNetworkInterfaceオブジェクトを取得しています。そして、各NetworkInterfaceオブジェクトに対して表1のメソッドをコールしているだけです。

以下に情報を取得して、表示するメソッドを示します。

    private void showInterfaceDetail(NetworkInterface netInterface)
                                           throws SocketException {
        // 名前
        System.out.println("Name: "
                           + netInterface.getName());
 
        // 表示名
        System.out.println("Display Name: "
                           + netInterface.getDisplayName());
 
        // アドレス
        List<InterfaceAddress> addresses 
            = netInterface.getInterfaceAddresses();
        for (InterfaceAddress address: addresses) {
            System.out.println("Address: ");
            // アドレス
            System.out.println("  Address: "
                + address.getAddress());
            // ブロードキャストアドレス
            System.out.println("  Broadcast: "
                + address.getBroadcast());
            // ネットワーク接頭辞長
            System.out.println("  Prefix Length: "
                + address.getNetworkPrefixLength());
        }
 
        // サブインタフェース
        Enumeration<NetworkInterface> subInterfaces
            = netInterface.getSubInterfaces();
        while(subInterfaces.hasMoreElements()) {
            System.out.println("Sub Interface: "
                + subInterfaces.nextElement().getDisplayName());
        }

        // サブインタフェースだった場合の親インタフェース
        NetworkInterface parent = netInterface.getParent();
        if (parent != null) {
            System.out.println("Parent Interface: "
                               + parent.getDisplayName());
        }
 
        // 接続状態
        System.out.println("起動中: "
            + (netInterface.isUp()? "YES": "NO"));
   
       // ループバック
        System.out.println("ループバック: " 
            + (netInterface.isLoopback()? "YES": "NO"));
  
        // Point to Point
        System.out.println("PPP: "
            + (netInterface.isPointToPoint()? "YES": "NO"));
   
        // マルチキャストのサポート
        System.out.println("マルチキャスト: " 
            + (netInterface.supportsMulticast()? "可": "不可"));
   
        // 物理アドレス
        byte hwAddress[] = netInterface.getHardwareAddress();
        if (hwAddress != null) {
            System.out.print("MAC アドレス: ");
            for (byte segment: hwAddress) {
                System.out.printf("%02x ", segment);
            }
            System.out.println();
        }
  
        // MTU
        System.out.println("MTU: " + netInterface.getMTU());
   
        // 仮想インタフェース
        System.out.println("仮想インタフェース: " 
            + (netInterface.isVirtual()? "YES": "NO"));
  
        System.out.println();
    }

さて、これを実行してみましょう。ここではWindows XPを使用し、ネットワークインタフェースは有線を使用しているPCで実行してみました。

C:\>java NetworkInterfaceSample
Name: lo
Display Name: MS TCP Loopback interface
Address:
  Address: /127.0.0.1
  Broadcast: /127.255.255.255
  Prefix Length: 8
起動中: YES
ループバック: YES
PPP: NO
マルチキャスト: 可
MTU: 1520
仮想インタフェース: NO
 
Name: eth0
Display Name: Intel(R) PRO/100 VE Network Connection - ?p?P?b?g ?X?P?W
Address:
  Address: /192.168.XXX.XXX
  Broadcast: /192.168.XXX.255
  Prefix Length: 21
起動中: YES
ループバック: NO
PPP: NO
マルチキャスト: 可
MAC アドレス: XX XX XX XX XX XX
MTU: 1500
仮想インタフェース: NO

実行した結果、ループバックとイーサネットのインタフェースが取得できました。なお、IPアドレスとMACアドレスは伏せ字にさせていただきました。

eth0はDisplay Nameが文字化けを起こしています。これはShift_JISでパケット スケと書かれています。Javaはこの文字をISO-8859-1として扱ってしまったため、文字化けしてしまったようです。

これに対し、Windows Vistaではアルファベット表示に変更されているので、文字化けは発生しません。

このように各ネットワークインタフェースの情報を取得できるようになりました。これらの情報を使用することはほとんどないかもしれません。とはいうものの、取得できるのとできないのでは大違いなのです。

著者紹介 櫻庭祐一

横河電機 ネットワーク開発センタ所属。Java in the Box 主筆

今月の櫻庭

ここ数年、夏になると沖縄にいっています。去年までは雨に降られたことがなかったのですが、今年はとうとう台風に遭遇してしまいました。

沖縄のJavaコミュニティであるJava Kücheの一周年記念講演会で講演するため、先月の12日に沖縄に向かいました。ところが、同じく沖縄に来ていたのが台風4号。せっかくの、講演会も中止の憂き目にあってしまいました。

それでも、懇親会だけは開かれました。居酒屋にプロジェクターを持ち込み、講演の内容についてざっくばらんにお話しすることができました。

それにしても、沖縄の台風はすごいとは聞いていましたが、本当にすごかったです。

泊まっていたホテルは建物全体が風で揺れ、窓のサッシからも雨がしみこんできます。倒れているヤシの木も多数。

沖縄でも、今回のような大型台風の直撃は久しぶりだそうです。

なお、中止になってしまった講演会ですが、 8/8に再び講演会が企画されています。残念ながら櫻庭は参加できませんが、ひがやすをさんと羽生章洋さんが講演されます。ご興味をお持ちの方はぜひ参加してみてはいかがでしょうか。

Presentiment of Typhoon, Okinawa 台風, 沖縄 台風, 沖縄
台風の予感が... 砂浜は海に飲みこまれました 視界はほとんどありません
Java Kuche 懇親会, おもろ殿内, 沖縄 Java Kuche 懇親会, おもろ殿内, 沖縄
こんな感じで話をしました。話しているのは鈴木雄介さん ゴーヤチャンプルを食べながら