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.
Há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.