1前書き

この記事では、一対多(ブロードキャスト)および一対多(マルチキャスト)通信をJavaで処理する方法について説明します。この記事で概説したブロードキャストとマルチキャストの概念は、UDPプロトコルに基づいています。

まず、データグラムとブロードキャスト、そしてそれがJavaでどのように実装されているかを簡単に説明します。また、ブロードキャストのデメリットを調べ、ブロードキャストの代わりにマルチキャストを提案します。

最後に、IPv4とIPv6の両方におけるこれら2つのアドレス指定方式のサポートについて説明します。


2データグラム要約

データグラムのhttps://docs.oracle.com/javase/tutorial/networking/datagrams/[公式な定義]によると、「データグラムは、到着、到着時間、ネットワークを介して送信される独立した自己完結型のメッセージです。そして内容は保証されません」。

Javaでは、

java.net

パッケージは、UDPプロトコルによる通信に使用できる

DatagramPacket

クラスと

DatagramSocket

クラスを公開しています。 UDPは通常、オーディオ/ビデオストリーミング、ネットワーク検出など、配信保証よりも低遅延の方が重要なシナリオで使用されます。

JavaでのUDPとデータグラムの詳細については、リンク:/udp-in-java[JavaによるUDPのガイド]を参照してください。


3


放送

同報通信は、1対全タイプの通信であり、すなわち、その意図は、データグラムをネットワーク内のすべてのノードに送信することである。

ポイントツーポイント通信の場合とは異なり、


ターゲットホストのIPアドレスを知る必要はありません

。代わりに、ブロードキャストアドレスが使用されます。

IPv4プロトコルに従って、ブロードキャストアドレスは論理アドレスで、ネットワークに接続されているデバイスはパケットを受信できます。この例では、ローカルネットワークのブロードキャストアドレスである

255.255.255.255

という特定のIPアドレスを使用します。

定義上、ローカルネットワークを他のネットワークに接続するルーターは、このデフォルトのブロードキャストアドレスに送信されたパケットを転送しません。後で、すべての

NetworkInterface

を繰り返し処理し、それぞれのブロードキャストアドレスにパケットを送信する方法も示します。

まず、メッセージのブロードキャスト方法を説明します。この範囲で、パケットがブロードキャストされることを知らせるためにソケット上で

setBroadcast()

メソッドを呼び出す必要があります。

public class BroadcastingClient {
    private static DatagramSocket socket = null;

    public static void main((String[]args)) throws IOException {
        broadcast("Hello", InetAddress.getByName("255.255.255.255"));
    }

    public static void broadcast(
      String broadcastMessage, InetAddress address) throws IOException {
        socket = new DatagramSocket();
        socket.setBroadcast(true);

        byte[]buffer = broadcastMessage.getBytes();

        DatagramPacket packet
          = new DatagramPacket(buffer, buffer.length, address, 4445);
        socket.send(packet);
        socket.close();
    }
}

次のスニペットは、ブロードキャストアドレスを見つけるためにすべての

NetworkInterfaces

を反復処理する方法を示しています。

List<InetAddress> listAllBroadcastAddresses() throws SocketException {
    List<InetAddress> broadcastList = new ArrayList<>();
    Enumeration<NetworkInterface> interfaces
      = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements()) {
        NetworkInterface networkInterface = interfaces.nextElement();

        if (networkInterface.isLoopback() || !networkInterface.isUp()) {
            continue;
        }

        networkInterface.getInterfaceAddresses().stream()
          .map(a -> a.getBroadcast())
          .filter(Objects::nonNull)
          .forEach(broadcastList::add);
    }
    return broadcastList;
}

ブロードキャストアドレスのリストを取得したら、上記の__broadcast()メソッドのコードをこれらの各アドレスに対して実行できます。

ブロードキャストメッセージを受信するために

受信側に特別なコードは必要ありません

。通常のUDPデータグラムを受け取るのと同じコードを再利用できます。このトピックに関する詳細は、

JavaによるUDPのガイド

にあります。


4マルチキャスト

通信を受信することに関心があるかどうかにかかわらず、ネットワーク内のすべてのノードにパケットが送信されるため、ブロードキャストは非効率的です。これはリソースの無駄遣いかもしれません。

マルチキャストはこの問題を解決し、関心のある消費者だけにパケットを送信します。

マルチキャストはグループメンバシップの概念

に基づいています。** マルチキャストアドレスは各グループを表します。

IPv4では、224.0.0.0から239.255.255.255までの任意のアドレスをマルチキャストアドレスとして使用できます。グループに加入しているノードだけが、そのグループに通信されたパケットを受信します。

Javaでは、

MulticastSocket

を使用してマルチキャストIPに送信されたパケットを受信します。次の例は、

MulticastSocket

の使用方法を示しています。

public class MulticastReceiver extends Thread {
    protected MulticastSocket socket = null;
    protected byte[]buf = new byte[256];

    public void run() {
        socket = new MulticastSocket(4446);
        InetAddress group = InetAddress.getByName("230.0.0.0");
        socket.joinGroup(group);
        while (true) {
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
            String received = new String(
              packet.getData(), 0, packet.getLength());
            if ("end".equals(received)) {
                break;
            }
        }
        socket.leaveGroup(group);
        socket.close();
    }
}


MulticastSocket

をポートにバインドした後、マルチキャストIPを引数として

joinGroup()

メソッドを呼び出します。これはこのグループに発行されたパケットを受信できるようにするために必要です。

leaveGroup()

メソッドを使用してグループを離れることができます。

次の例は、マルチキャストIPに発行する方法を示しています。

public class MulticastPublisher {
    private DatagramSocket socket;
    private InetAddress group;
    private byte[]buf;

    public void multicast(
      String multicastMessage) throws IOException {
        socket = new DatagramSocket();
        group = InetAddress.getByName("230.0.0.0");
        buf = multicastMessage.getBytes();

        DatagramPacket packet
          = new DatagramPacket(buf, buf.length, group, 4446);
        socket.send(packet);
        socket.close();
    }
}


5ブロードキャストとIPv6

IPv4は、ユニキャスト、ブロードキャスト、およびマルチキャストの3種類のアドレス指定をサポートしています。ブロードキャストは、理論的には、一対多の通信です。つまり、デバイスから送信されたパケットは、インターネット全体に到達する可能性があります。

これは明白な理由から望ましくないので、IPv4ブロードキャストの範囲は大幅に縮小されました。マルチキャストは、ブロードキャストよりも優れた代替手段としても機能しますが、かなり後になって採用されるようになりました。

  • IPv6では、マルチキャストサポートが必須になり、ブロードキャストの明確な概念はありません** マルチキャストは、すべてのブロードキャスト機能が何らかの形式のマルチキャストで実装できるように拡張および改良されました。

IPv6では、アドレスの左端のビットを使用してその種類を判別します。マルチキャストアドレスの場合、最初の8ビットはすべて1です。

FF00 ::/8。さらに、ビット113〜116は、アドレスの範囲を表し、これは、グローバル、サイトローカル、リンクローカル、ノードローカルのいずれかであり得る。

ユニキャストとマルチキャストに加えて、IPv6はエニーキャストもサポートしています。パケットはグループの任意のメンバーに送信できますが、すべてのメンバーに送信する必要はありません。


6. 概要

この記事では、UDPプロトコルを使用した1対多および1対多タイプの通信の概念について説明しました。これらの概念をJavaで実装する方法の例を見ました。

最後に、IPv4とIPv6のサポートについても調べました。

完全なサンプルコードはhttps://github.com/eugenp/tutorials/tree/master/core-java/src/main/java/com/baeldung/networking/udp[Githubで入手可能]です。