Sockets com Java – Parte III
Aprenda a desenvolver aplicações em Java que comunicam-se via rede local ou internet...
Aprenda a desenvolver aplicações em Java que comunicam-se via rede local ou internet
O protocolo UDP
Quando necessitamos de uma troca não confiável de informações podemos usar o protocolo UDP (User Datagram Protocol), pois este protocolo não garante a entrega dos pacotes (o UDP não espera uma mensagem de confirmação do host de destino). É de responsabilidade da aplicação receptora a remontagem dos pacotes na ordem correta e a solicitação de reenvio de pacotes que não foram recebidos. O UDP utiliza datagram sockets para a troca de mensagens. As principais aplicações do UDP são aplicações como transmissões de vídeo, skype, voip, etc... Para exemplificar imagine um serviço de voz sobre IP onde um pacote é perdido enquanto dois usuários conversam, não faz sentido reenviar o pacote pois o usuário da outra ponta precisaria saber que ainda faltam pacotes a receber. Veja uma simulação abaixo da conversa entre dois usuários:
· Erika: Ola Paulo
· Paulo: Ola Erika
· Erika: Como você está?
· Paulo: Tudo bem e vc? (este pacote foi perdido)
No exemplo acima o TCP enviaria novamente o pacote e o usuário da outra ponta deveria ficar esperando. Não faria nenhum sentido isso tratando-se de uma ligação telefônica. Este é um típico caso onde o UDP se aplica perfeitamente.
Os datagram sockets são mensagens que podem ser enviadas pela rede quando não existe a necessidade de confirmação de entrega, de tempo de entrega e nem mesmo garantia de conteúdo. Datagramas são úteis em aplicações que não necessitam do estabelecimento de uma conexão para o envio da mensagem. Um bom exemplo do seu uso é o envio de mensagens em broadcast para clientes de uma rede (o servidor pode enviar um datagrama para todos os clientes avisando que irá reiniciar, por exemplo). Em Java podemos trabalhar com datagramas utilizando as classes DatagramPacket e DatagramSocket do pacote java.net.
Um servidor UDP básico
Antes de mostramos como criar um servidor TCP capaz de receber várias conexões simultâneas, vamos mostrar como criar um servidor UDP. Como vimos, o UDP envia os pacotes sem esperar por uma resposta do receptor. Este protocolo pode ser útil em situações como o envio de pacotes multimídia, por exemplo, ou um serviço de voz sobre ip, o que é muito comum.
Nosso servidor UDP envia mensagens para os clientes de uma determinada rede local. Perceba neste exemplo que no UDP o cliente também aguarda mensagens que poderão ser enviadas pelo servidor, ou seja, mantém um DatagramSocket em uma determinada porta. Por exemplo, o seguinte trecho cria o DatagramSocket que irá esperar mensagens na porta 12346.
DatagramSocket serverdgram = new DatagramSocket(12346);
Veja na Listagem 3 o remetente UDP exemplo e na Listagem 4 o código do receptor UDP, na Figura 4 você pode ver a mensagem sendo enviada pelo remetente. Na Figura 5 temos o receptor sendo inicializado para receber as mensagens e na Figura 6 a mensagem recebida pelo receptor. Como estamos usando UDP neste caso o remetente sempre vai mostrar a mensagem indicando que a mensagem foi enviada, porém não existe a confirmação de que a mensagem foi recebida.
Listagem 3. Classe RemetenteUDP
public class RemetenteUDP {
public static void main(String[] args) {
if(args.length != 3) {
System.out.println("Uso correto: <Nome da maquina> <Porta> <Mensagem>");
System.exit(0);
}
try {
//Primeiro argumento é o nome do host destino
InetAddress addr = InetAddress.getByName(args[0]);
int port = Integer.parseInt(args[1]);
byte[] msg = args[2].getBytes();
//Monta o pacote a ser enviado
DatagramPacket pkg = new DatagramPacket(msg,msg.length, addr, port);
// Cria o DatagramSocket que será responsável por enviar a mensagem
DatagramSocket ds = new DatagramSocket();
//Envia a mensagem
ds.send(pkg);
System.out.println("Mensagem enviada para: " + addr.getHostAddress() + "\n" +
"Porta: " + port + "\n" + "Mensagem: " + args[2]);
//Fecha o DatagramSocket
ds.close();
}
catch(IOException ioe) {...}
}
}
Listagem 4. Classe ReceptorUDP
public class ReceptorUDP {
public static void main(String[] args) {
if(args.length != 1) {
System.out.println("Informe a porta a ser ouvida");
System.exit(0);
}
try {
//Converte o argumento recebido para inteiro (numero da porta)
int port = Integer.parseInt(args[0]);
//Cria o DatagramSocket para aguardar mensagens, neste momento o método fica bloqueando
//até o recebimente de uma mensagem
DatagramSocket ds = new DatagramSocket(port);
System.out.println("Ouvindo a porta: " + port);
//Preparando o buffer de recebimento da mensagem
byte[] msg = new byte[256];
//Prepara o pacote de dados
DatagramPacket pkg = new DatagramPacket(msg, msg.length);
//Recebimento da mensagem
ds.receive(pkg);
JOptionPane.showMessageDialog(null,new String(pkg.getData()).trim(),
"Mensagem recebida",1);
ds.close();
}
catch(IOException ioe) {...}
}
}
Figura 4. Remetente UDP em ação (enviando mensagem ao receptor)
Figura 5. Receptor sendo inicializado para receber mensagens na porta 1234
Figura 6. Mensagem UDP recebida pelo receptor
Paulo Sérgio Pereira
Paulo Sergio Pereira (psergio.p@terra.com.br) Bacharel em Ciência da Computação pela Univap (Universidade do Vale do Paraíba) é desenvolvedor Java, Progress, Visual Basic, Visual C++.NET e ADVPL. É administrador de bancos de dados Progress, SQL Server 2000/2005 e DB2. Atua como desenvolvedor pela em...



