Transmissão e Multicasting em Java

Transmissão e Multicasting em Java

1. Introdução

Neste artigo, descrevemos como as comunicações um para todos (Broadcast) e um para muitos (Multicast) podem ser tratadas em Java. Os conceitos de transmissão e multicast descritos neste artigo são baseados no protocolo UDP.

Começamos com uma rápida recapitulação dos datagramas e da transmissão e como eles são implementados em Java. Também analisamos as desvantagens da transmissão e propomos o multicast como uma alternativa à transmissão.

Por fim, concluímos discutindo o suporte para esses dois métodos de endereçamento no IPv4 e no IPv6.

2. Recapitulação do Datagrama

De acordo com oofficial definition de um datagrama, “Um datagrama é uma mensagem independente e autocontida enviada pela rede cuja chegada, hora de chegada e conteúdo não são garantidos”.

Em Java, o pacotejava.net expõe as classesDatagramPacketeDatagramSocket que podem ser usadas para comunicação por meio do protocolo UDP. O UDP é normalmente usado em cenários em que menor latência é mais importante que a entrega garantida, como streaming de áudio / vídeo, descoberta de rede, etc.

Para saber mais sobre UDP e datagramas em Java, consulteA Guide to UDP in Java.

3. Broadcasting

A transmissão é um tipo de comunicação um para todos, ou seja, a intenção é enviar o datagrama para todos os nós da rede. Unlike in the case of point-to-point communication,we don’t have to know the target host’s IP Address. Em vez disso, um endereço de broadcast é usado.

Conforme o protocolo IPv4, um endereço de broadcast é um endereço lógico, no qual os dispositivos conectados à rede estão habilitados para receber pacotes. Em nosso exemplo, usamos um endereço IP específico,255.255.255.255, que é o endereço de broadcast da rede local.

Por definição, os roteadores que conectam uma rede local a outras redes não encaminham pacotes enviados para este endereço de broadcast padrão. Posteriormente, também mostraremos como podemos iterar por todos osNetworkInterfaces e enviar pacotes para seus respectivos endereços de broadcast.

Primeiro, demonstramos como transmitir uma mensagem. Nesse sentido, precisamos chamar o métodosetBroadcast() no soquete para que ele saiba que o pacote será transmitido:

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

O próximo snippet mostra como iterar por todos osNetworkInterfaces para encontrar seu endereço de transmissão:

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

Assim que tivermos a lista de endereços de broadcast, podemos executar o código no métodobroadcast() mostrado acima para cada um desses endereços.

no special code required on the receiving side para receber uma mensagem transmitida. Podemos reutilizar o mesmo código que recebe um datagrama UDP normal. A Guide to UDP in Java contém mais detalhes sobre este tópico.

4. Multicasting

A transmissão é ineficiente, pois os pacotes são enviados a todos os nós da rede, independentemente de estarem interessados ​​em receber a comunicação ou não. Isso pode ser um desperdício de recursos.

A difusão seletiva resolve esse problema e envia pacotes apenas aos consumidores interessados. Multicasting is based on a group membership concept, onde um endereço multicast representa cada grupo.

No IPv4, qualquer endereço entre 224.0.0.0 a 239.255.255.255 pode ser usado como um endereço multicast. Somente os nós que assinam um grupo recebem pacotes comunicados ao grupo.

Em Java,MulticastSocket é usado para receber pacotes enviados para um IP multicast. O exemplo a seguir demonstra o uso 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();
    }
}

Depois de vincularMulticastSocket a uma porta, chamamos o métodojoinGroup(), com o IP multicast como argumento. Isso é necessário para poder receber os pacotes publicados para este grupo. O métodoleaveGroup() pode ser usado para deixar o grupo.

O exemplo a seguir mostra como publicar em um IP multicast:

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. Broadcast e IPv6

O IPv4 suporta três tipos de endereçamento: unicast, broadcast e multicast. A transmissão, em teoria, é uma comunicação um para todos, ou seja, um pacote enviado de um dispositivo tem o potencial de alcançar toda a Internet.

Como isso é indesejável por razões óbvias, o escopo da transmissão IPv4 foi significativamente reduzido. O multicast, que também serve como uma alternativa melhor à transmissão, chegou muito mais tarde e, portanto, ficou para adoção.

In IPv6, multicast support has been made mandatory, and there is no explicit concept of broadcasting. O multicast foi estendido e aprimorado para que todos os recursos de transmissão possam agora ser implementados com alguma forma de multicast.

No IPv6, os bits mais à esquerda de um endereço são usados ​​para determinar seu tipo. Para um endereço multicast, os primeiros 8 bits são todos, ou seja, FF00::/8. Além disso, o bit 113-116 representa o escopo do endereço, que pode ser um dos seguintes 4: Global, Local do Site, Local do Link, Local do Nó.

Além do unicast e do multicast, o IPv6 também suporta anycast, no qual um pacote pode ser enviado a qualquer membro do grupo, mas não precisa ser enviado a todos os membros.

6. Sumário

Neste artigo, exploramos os conceitos do tipo de comunicação um para todos e um para muitos usando o protocolo UDP. Vimos exemplos de como implementar esses conceitos em Java.

Por fim, também exploramos o suporte a IPv4 e IPv6.

O código de exemplo completo está disponívelover on Github.