Diffusion et multidiffusion en Java

Diffusion et multidiffusion en Java

1. introduction

Dans cet article, nous décrivons comment les communications un à tous (diffusion) et un à plusieurs (multidiffusion) peuvent être gérées en Java. Les concepts de diffusion et de multidiffusion décrits dans cet article sont basés sur le protocole UDP.

Nous commençons par une récapitulation rapide des datagrammes et de la diffusion, ainsi que de la manière dont elle est mise en œuvre en Java. Nous examinons également les inconvénients de la radiodiffusion et proposons la multidiffusion comme alternative à la radiodiffusion.

Enfin, nous concluons en discutant de la prise en charge de ces deux méthodes d’adressage à la fois dans IPv4 et IPv6.

2. Récapitulatif du datagramme

Selon lesofficial definition d'un datagramme, «Un datagramme est un message indépendant et autonome envoyé sur le réseau dont l'arrivée, l'heure d'arrivée et le contenu ne sont pas garantis».

En Java, le packagejava.net expose les classesDatagramPacket etDatagramSocket qui peuvent être utilisées pour la communication via le protocole UDP. Le protocole UDP est généralement utilisé dans des scénarios où une latence plus basse est plus importante que la livraison garantie, telle que le streaming audio / vidéo, la découverte du réseau, etc.

Pour en savoir plus sur UDP et les datagrammes en Java, reportez-vous àA Guide to UDP in Java.

3. Broadcasting

La radiodiffusion est un type de communication un à tous, c.-à-d. L'intention est d'envoyer le datagramme à tous les nœuds du réseau. Unlike in the case of point-to-point communication,we don’t have to know the target host’s IP Address. Au lieu de cela, une adresse de diffusion est utilisée.

Selon le protocole IPv4, une adresse de diffusion est une adresse logique sur laquelle les périphériques connectés au réseau sont autorisés à recevoir des paquets. Dans notre exemple, nous utilisons une adresse IP particulière,255.255.255.255, qui est l'adresse de diffusion du réseau local.

Par définition, les routeurs connectant un réseau local à d'autres réseaux ne transfèrent pas les paquets envoyés à cette adresse de diffusion par défaut. Plus tard, nous montrons également comment nous pouvons parcourir tous lesNetworkInterfaces et envoyer des paquets à leurs adresses de diffusion respectives.

Tout d'abord, nous montrons comment diffuser un message. Dans cette mesure, nous devons appeler la méthodesetBroadcast() sur le socket pour lui faire savoir que le paquet doit être diffusé:

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();
    }
}

L'extrait suivant montre comment parcourir tous lesNetworkInterfaces pour trouver leur adresse de diffusion:

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;
}

Une fois que nous avons la liste des adresses de diffusion, nous pouvons exécuter le code dans la méthodebroadcast() ci-dessus pour chacune de ces adresses.

Il y ano special code required on the receiving side pour recevoir un message diffusé. Nous pouvons réutiliser le même code qui reçoit un datagramme UDP normal. A Guide to UDP in Java contient plus de détails sur ce sujet.

4. Multidiffusion

La diffusion est inefficace car les paquets sont envoyés à tous les nœuds du réseau, qu’ils soient intéressés ou non à recevoir la communication. Cela peut être un gaspillage de ressources.

La multidiffusion résout ce problème et envoie des paquets uniquement aux consommateurs intéressés. Multicasting is based on a group membership concept, où une adresse multicast représente chaque groupe.

En IPv4, toute adresse comprise entre 224.0.0.0 et 239.255.255.255 peut être utilisée comme adresse de multidiffusion. Seuls les nœuds abonnés à un groupe reçoivent les paquets communiqués au groupe.

En Java,MulticastSocket est utilisé pour recevoir des paquets envoyés à une adresse IP multicast. L'exemple suivant illustre l'utilisation deMulticastSocket:

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();
    }
}

Après avoir lié lesMulticastSocket à un port, nous appelons la méthodejoinGroup(), avec l'adresse IP de multidiffusion comme argument. Cela est nécessaire pour pouvoir recevoir les paquets publiés dans ce groupe. La méthodeleaveGroup() peut être utilisée pour quitter le groupe.

L'exemple suivant montre comment publier sur une adresse IP multidiffusion:

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. Diffusion et IPv6

IPv4 prend en charge trois types d'adressage: unicast, broadcast et multicast. La diffusion, en théorie, est une communication unique, c’est-à-dire un paquet envoyé à partir d'un appareil a le potentiel d'atteindre l'internet tout entier.

Comme cela n’est pas souhaitable pour des raisons évidentes, la portée de la diffusion IPv4 a été considérablement réduite. La multidiffusion, qui constitue également une meilleure alternative à la diffusion, est arrivée beaucoup plus tard et a donc pris du retard dans son adoption.

La multidiffusion deIn IPv6, multicast support has been made mandatory, and there is no explicit concept of broadcasting. a été étendue et améliorée afin que toutes les fonctionnalités de diffusion puissent désormais être implémentées avec une forme de multidiffusion.

Dans IPv6, les bits les plus à gauche d'une adresse sont utilisés pour déterminer son type. Pour une adresse de multidiffusion, les 8 premiers bits sont tous des unités, c'est-à-dire FF00::/8. De plus, les bits 113 à 116 représentent l'étendue de l'adresse, qui peut être l'une des 4 suivantes: globale, locale au site, locale au lien, locale au noeud.

Outre la monodiffusion et la multidiffusion, IPv6 prend également en charge le anycast, dans lequel un paquet peut être envoyé à n’importe quel membre du groupe, mais n’a pas besoin d’être envoyé à tous les membres.

6. Sommaire

Dans cet article, nous avons exploré les concepts de type de communication un à tous et un à plusieurs à l'aide du protocole UDP. Nous avons vu des exemples montrant comment implémenter ces concepts en Java.

Enfin, nous avons également exploré le support IPv4 et IPv6.

Un exemple de code complet est disponibleover on Github.