Quando utilizamos sockets udp nós precisamos levar em consideração quatro características muito importantes:
- É um canal não confiável
- Não garante entrega dos datagramas
- Pode entregar datagramas duplicados
- Não garante ordem de entrega dos datagramas
- Não tem estado de conexão (escuta, estabelecida)
Para trabalhar com socket udp nós utilizamos apenas duas classes, são elas:
- DatagramSocket
- DatagramPacket
O DatagramSocket é responsável por criar o servidor e o cliente. Para criar o servidor nós passamos a porta como argumento na inicialização do objeto. Já para o cliente, nós não passamos argumentos na instanciação do objeto, contudo utilizamos argumentos para os dados de conexão, exemplo: socket.connect("ip", porta);
.
Diferentemente do socket via TCP nós não temos abstrações para trabalhar com o envio de dados pela rede, temos que trabalhar diretamente com o envio e recebimento de array de bytes. Dica: uma string sempre possui o método getBytes(), este método retorna uma array de bytes com o conteúdo da string.
O DatagramPacket é a classe responsável por encapsular os dados que serão enviados e recebidos. Quando quisermos enviar algo precisamos criar um datagramPacket, passando como argumento a array de bytes que queremos enviar, o tamanho da array de bytes, endereço ip, porta.
Neste exemplo o servidor é inicializado na porta 7171 e recebe pacotes de 1024 bytes, após o recebimento ele envia um outro pacote com uma string para o endereço de quem enviou o pacote para ele.
public class Servidor {
public static void main(String[] args) {
try {
// Temos um servidor UDP instanciado
DatagramSocket servidor = new DatagramSocket(7171);
// Recebe e envia pacotes
byte[] espacoDeArmazenamento = new byte[1024];
DatagramPacket pacote = new DatagramPacket(espacoDeArmazenamento, espacoDeArmazenamento.length);
// Dizemos agora pro socket que nós esperamos receber um pacote
servidor.receive(pacote);
// Mostramos na tela o que foi recebido
System.out.println(new String(pacote.getData()));
/*
* Depois de recebemos um pacote, nós temos o endereço e porta de quem enviou e
* estas informações estão dentro do DatagramPacket recebido
*/
String informacaoDeEnvio = "Oi cliente!";
DatagramPacket pacoteDeEnvio = new DatagramPacket(informacaoDeEnvio.getBytes(), informacaoDeEnvio.getBytes().length, pacote.getSocketAddress());
servidor.send(pacoteDeEnvio);
} catch (IOException e) {}
}
}
O cliente conecta em um endereço do tipo InetAddress (é preciso cria-lo), instancia a mensagem, instancia o pacote e envia o pacote. Posteriormente ele também recebe uma mensagem e imprime na tela.
public class Cliente {
public static void main(String[] args) {
try {
// Criamos um endereço (é necessário)
InetAddress endereco = InetAddress.getByName("localhost");
// Criamos uma conexão socket
DatagramSocket socket = new DatagramSocket();
socket.connect(endereco, 7171);
// Uma string pode ser convertida para um array de bytes
String mensagem = "fala servidor";
// Criamos um pacote a ser enviado
DatagramPacket pacote = new DatagramPacket(mensagem.getBytes(), mensagem.length());
// Enviamos o pacote
socket.send(pacote);
// O servidor envia algo para nós
DatagramPacket recebendo = new DatagramPacket(new byte[100], 100);
socket.receive(recebendo);
System.out.println(new String(recebendo.getData()));
} catch (IOException e) {}
}
}