Javaでのブロードキャストとマルチキャスト

Javaでのブロードキャストとマルチキャスト

1. 前書き

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

データグラムとブロードキャストの簡単な要約と、Javaでの実装方法から始めます。 また、ブロードキャストの欠点を検討し、ブロードキャストの代替手段としてマルチキャストを提案します。

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

2. データグラムの要約

データグラムのofficial definitionによると、「データグラムは、ネットワークを介して送信される独立した自己完結型のメッセージであり、到着、到着時間、およびコンテンツは保証されていません」。

Javaでは、java.netパッケージは、UDPプロトコルを介した通信に使用できるDatagramPacketクラスとDatagramSocketクラスを公開します。 UDPは通常、オーディオ/ビデオストリーミング、ネットワーク検出など、保証された配信よりもレイテンシが低いことが重要なシナリオで使用されます。

JavaのUDPとデータグラムの詳細については、A Guide to UDP in Javaを参照してください。

3Broadcasting

ブロードキャストは、1対すべてのタイプの通信です。 その意図は、ネットワーク内のすべてのノードにデータグラムを送信することです。 Unlike in the case of point-to-point communication,we don’t have to know the target host’s IP Address。 代わりに、ブロードキャストアドレスが使用されます。

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

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

最初に、メッセージをブロードキャストする方法を示します。 この点で、ソケットで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 listAllBroadcastAddresses() throws SocketException {
    List broadcastList = new ArrayList<>();
    Enumeration 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()メソッドでコードを実行できます。

ブロードキャストされたメッセージを受信するためのno special code required on the receiving sideがあります。 通常のUDPデータグラムを受け取る同じコードを再利用できます。 A Guide to UDP in Javaには、このトピックに関する詳細が含まれています。

4. マルチキャスト

通信の受信に関心があるかどうかに関係なく、ネットワーク内のすべてのノードにパケットが送信されるため、ブロードキャストは非効率的です。 これはリソースの浪費かもしれません。

マルチキャストはこの問題を解決し、興味のある消費者のみにパケットを送信します。 Multicasting is based on a group membership concept、ここでマルチキャストアドレスは各グループを表します。

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種類のアドレス指定をサポートしています。 ブロードキャストは、理論的には、1対1のコミュニケーションです。 デバイスから送信されたパケットは、インターネット全体に到達する可能性があります。

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

In IPv6, multicast support has been made mandatory, and there is no explicit concept of broadcasting.マルチキャストが拡張および改善され、すべてのブロードキャスト機能を何らかの形式のマルチキャストで実装できるようになりました。

IPv6では、アドレスの左端のビットを使用してそのタイプが判別されます。 マルチキャストアドレスの場合、最初の8ビットはすべて1です。 FF00::/8. さらに、ビット113〜116はアドレスの範囲を表します。アドレスの範囲は、グローバル、サイトローカル、リンクローカル、ノードローカルのいずれかです。

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

6. 概要

この記事では、UDPプロトコルを使用した一対一および一対多の通信の概念を検討しました。 これらの概念をJavaで実装する方法の例を見ました。

最後に、IPv4およびIPv6のサポートについても調査しました。

完全なサンプルコードはover on Githubで入手できます。