1概要

この記事では、ネットワークインターフェースと、Javaでプログラム的にアクセスする方法に焦点を当てます。

簡単に言えば、

ネットワークインタフェースは、デバイスとそのネットワーク接続

の間の相互接続のポイントです。

日常的な言葉では、ネットワークインタフェースカード(NIC)という用語でそれらを指しますが、すべてがハードウェア形式である必要はありません。

たとえば、Webおよびネットワークアプリケーションのテストによく使用される一般的なlocalhost IP

127.0.0.1

は、ループバックインタフェースです。これは直接のハードウェアインタフェースではありません。

もちろん、システムには有線イーサネット、WIFI、Bluetoothなどのような複数のアクティブネットワーク接続があることが多い

Javaでは、それらと直接対話するために使用できる主なAPIは

java.net.NetworkInterface

クラスです。それで、すぐに始めるために、完全なパッケージをインポートしましょう:

import java.net.** ;

** 2ネットワークインタフェースにアクセスする理由

ほとんどのJavaプログラムは、おそらくそれらと直接やり取りすることはおそらくないでしょう。ただし、この種の低レベルのアクセスが必要な場合は特別なシナリオがあります。

これらの中で最も優れているのは、システムが複数のカードを持っていて、ソケットを

で使用するための特定のインタフェースを

自由に選択したい場合です。そのようなシナリオでは、我々は通常名前を知っていますが必ずしもIPアドレスを知っていません。

通常、ソケット接続を特定のサーバーアドレスにしたい場合は、

Socket socket = new Socket();
socket.connect(new InetSocketAddress(address, port));

このようにして、システムは適切なローカルアドレスを選び、それにバインドし、そしてそのネットワークインターフェースを通してサーバーと通信します。ただし、この方法では、自分で選択することはできません。

ここで仮定します。住所はわかりませんが、名前はわかります。デモンストレーションを目的として、ループバックインタフェース経由の接続が必要であるとします。慣例では、その名前は

lo

、少なくともLinuxおよびWindowsシステムでは、OSXでは

lo0

です。

NetworkInterface nif = NetworkInterface.getByName("lo");
Enumeration<InetAddress> nifAddresses = nif.getInetAddresses();

Socket socket = new Socket();
socket.bind(new InetSocketAddress(nifAddresses.nextElement(), 0));
socket.connect(new InetSocketAddress(address, port));

そのため、まず

lo

に接続されているネットワークインターフェースを取得し、それに接続されているアドレスを取得し、ソケットを作成して、コンパイル時にはわからない列挙型アドレスにバインドしてから接続します。


NetworkInterface

オブジェクトには、名前とそれに割り当てられたIPアドレスのセットが含まれています。したがって、これらのアドレスのいずれかにバインドすると、このインタフェースを介した通信が保証されます。

これは本当にAPIに関して特別なことを何も言っていません。ローカルアドレスをlocalhostにしたい場合は、バインディングコードを追加するだけで最初のスニペットで十分です。

さらに、localhostに1つのよく知られたアドレス

127.0.0.1

があり、ソケットをそれに簡単にバインドできるため、いくつかの手順をすべて実行する必要はまったくありません。

しかし、あなたの場合、

lo

はおそらくBluetoothのような他のインターフェースを表しているかもしれません –

net1

、無線ネットワーク –

net0

またはイーサネット

eth0

。このような場合は、コンパイル時にIPアドレスがわかりません。


3ネットワークインタフェースの取得

このセクションでは、利用可能なインタフェースを取得するための他の利用可能なAPIを探ります。前のセクションでは、これらのアプローチの1つだけを見ました。

getByName()

静的メソッド


NetworkInterface

クラスにはパブリックコンストラクタがないことに注意する必要があります。そのため、もちろん新しいインスタンスを作成することはできません。代わりに、利用可能なAPIを使用して取得します。

これまで見てきたAPIは、指定された名前でネットワークインターフェースを検索するために使用されます。

@Test
public void givenName__whenReturnsNetworkInterface__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");

    assertNotNull(nif);
}

名前がなければ

null

を返します。

@Test
public void givenInExistentName__whenReturnsNull__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("inexistent__name");

    assertNull(nif);
}

2番目のAPIは

getByInetAddress()

です。これも既知のパラメータを指定する必要があります。今回はIPアドレスを指定します。

@Test
public void givenIP__whenReturnsNetworkInterface__thenCorrect() {
    byte[]ip = new byte[]{ 127, 0, 0, 1 };

    NetworkInterface nif = NetworkInterface.getByInetAddress(
      InetAddress.getByAddress(ip));

    assertNotNull(nif);
}

またはホスト名:

@Test
public void givenHostName__whenReturnsNetworkInterface__thenCorrect()  {
    NetworkInterface nif = NetworkInterface.getByInetAddress(
      InetAddress.getByName("localhost"));

    assertNotNull(nif);
}

あるいはlocalhostに特化しているなら:

@Test
public void givenLocalHost__whenReturnsNetworkInterface__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByInetAddress(
      InetAddress.getLocalHost());

    assertNotNull(nif);
}

もう1つの方法は、ループバックインタフェースを明示的に使用することです。

@Test
public void givenLoopBack__whenReturnsNetworkInterface__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByInetAddress(
      InetAddress.getLoopbackAddress());

    assertNotNull(nif);
}

Java 7以降でのみ利用可能となった3番目のアプローチは、そのインデックスによってネットワークインタフェースを取得することです。

NetworkInterface nif = NetworkInterface.getByIndex(int index);

最後の方法は、

getNetworkInterfaces

APIを使用することです。システムで利用可能なすべてのネットワークインタフェースの

Enumeration

を返します。返されたオブジェクトをループで取得することが私たちの責任です。標準の慣用句では

List

を使用します。

Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();

for (NetworkInterface nif: Collections.list(nets)) {
   //do something with the network interface
}


4ネットワークインタフェースパラメータ

オブジェクトを取得した後に取得できる貴重な情報はたくさんあります。

最も有用なものの1つはそれに割り当てられたIPアドレスのリストです

2つのAPIを使ってIPアドレスを取得できます。最初のAPIは

getInetAddresses()

です。これは

InetAddress

インスタンスの

Enumeration

を返します。これらのインスタンスは適切と判断した場合に処理できます。

@Test
public void givenInterface__whenReturnsInetAddresses__thenCorrect()  {
    NetworkInterface nif = NetworkInterface.getByName("lo");
    Enumeration<InetAddress> addressEnum = nif.getInetAddresses();
    InetAddress address = addressEnum.nextElement();

    assertEquals("127.0.0.1", address.getHostAddress());
}

2番目のAPIは

getInterfaceAddresses()

です。これは、

InetAddress

インスタンスよりも強力な

List

of

InterfaceAddress

インスタンスを返します。たとえば、IPアドレスとは別に、ブロードキャストアドレスに興味があるかもしれません。

@Test
public void givenInterface__whenReturnsInterfaceAddresses__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");
    List<InterfaceAddress> addressEnum = nif.getInterfaceAddresses();
    InterfaceAddress address = addressEnum.get(0);

    InetAddress localAddress=address.getAddress();
    InetAddress broadCastAddress = address.getBroadcast();

    assertEquals("127.0.0.1", localAddress.getHostAddress());
    assertEquals("127.255.255.255",broadCastAddress.getHostAddress());
}

割り当てられた名前とIPアドレスを超えて、インターフェイスに関するネットワークパラメータにアクセスできます。稼働しているかどうかを確認するには

@Test
public void givenInterface__whenChecksIfUp__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");

    assertTrue(nif.isUp());
}

ループバックインタフェースかどうかを確認するには

@Test
public void givenInterface__whenChecksIfLoopback__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");

    assertTrue(nif.isLoopback());
}

ポイントツーポイントネットワーク接続であるかどうかを確認するには

@Test
public void givenInterface__whenChecksIfPointToPoint__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");

    assertFalse(nif.isPointToPoint());
}

または仮想インターフェースの場合

@Test
public void givenInterface__whenChecksIfVirtual__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");
    assertFalse(nif.isVirtual());
}

マルチキャストがサポートされているかどうかを確認するには

@Test
public void givenInterface__whenChecksMulticastSupport__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");

    assertTrue(nif.supportsMulticast());
}

または、通常はMACアドレスと呼ばれるその物理アドレスを取得するには、次のように入力します。

@Test
public void givenInterface__whenGetsMacAddress__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("lo");
    byte[]bytes = nif.getHardwareAddress();

    assertNotNull(bytes);
}

もう1つのパラメータは、このインタフェースを通じて送信できる最大パケットサイズを定義するMaximum Transmission Unitです。

@Test
public void givenInterface__whenGetsMTU__thenCorrect() {
    NetworkInterface nif = NetworkInterface.getByName("net0");
    int mtu = nif.getMTU();

    assertEquals(1500, mtu);
}


5結論

この記事では、ネットワーク・インターフェース、それらをプログラムでアクセスする方法、およびそれらにアクセスする必要がある理由について説明しました。

この記事で使用されている完全なソースコードとサンプルはhttps://github.com/eugenp/tutorials/tree/master/core-java/src/main/java/com/baeldung/networking[Githubプロジェクト]にあります。