Aprenda Java

  • Página Inicial
  • Contato!
  • Tudo sobre Java Parte 1!
  • Tudo sobre Java Parte 2!
  • Tudo sobre Java Parte 3!
  • Tudo sobre Java Parte 4!
  • Tudo sobre Java Parte 5!
  • Tudo sobre Java Parte 6!
  • Tudo sobre Java Parte 7!
  • Redes em Java - Parte 1

    Sockets em Java - Parte 1

    Primeiro entenda as diferenças entre TCP e UDP:

    TCP (Trasmission Control Protocol) UDP (Use Datagram Protocol)
    Orientado a conexão Orientado a datagrama
    É confiável Não é confiável
    Stream (segmentos) Datagramas (pacotes)
    Controle de fluxo e retrasmissão de mensagens Sem controle de fluxo
    Mensagens ordenadas Sem garantia de ordem ou chegada
    Recebimento dos segmentos é confirmado (ACK) Mais apropriado a broadcast e multicast
    Mais lento Mais rápido

    A comunicação cliente-servidor mais simples que existe em Java pode ser esquematizada, depois da conexão, qualquer lado pode iniciar a comunicação (o canal é bidirecional) e é assíncrona e bloqueante (em geral)..

    O servidor cria um socket associado a uma porta. A operação new ServerSocket() realiza as operações, depois espera conexões de clientes. Quando aceita conexão, um novo socket é criado para a conexão em uma nova porta e continua aceitando outras conexões na mesma porta enquanto ServerSocket() estiver instanciado.

    O cliente deve conhecer o nome e porta do servidor, é quem solicita a conexão, se a conexão é aceita pelo servidor, um socket é criado e associado a uma porta no cliente permitindo a conexão porta com porta.

    A classe Socket em Java não possui os equivalente da api C/C++, a entrada e saída de dados é feita por Streams, onde:

    Sockets em Java - Parte 2

    Crie um novo projeto sem classe principal, e crie duas classes, a Cliente e a Servidor.

    Na classe Cliente, colocamos esse código:

    
    package conexoes;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.Arrays;
    
    public class Cliente {
        public static void main(String[] args) {
            int porta = 33333; // Porta default do servidor
            String serv = "127.0.0.1"; // Endereço do servidor, no caso, o de loopback do próprio cliente, pode ser qualquer endereço
            
            byte conteudo[] = {1, 4, 5, 6, 14, 18, 2, 4, 10, 11, 9, 12, 13, 3}; // Bytes fora de ordem a serem transmitidos
            
            try {
                try(Socket sock = new Socket(serv, porta)) { // Importe
                    OutputStream out = sock.getOutputStream(); // Importe
                    out.write(conteudo); // Escrevemos os dados no Output para transmitir
                    
                    System.out.printf("Dados transmitidos para servidor %s: %04d.\n", serv, porta);
                    
                    InputStream in = sock.getInputStream(); // Importe
                    in.read(conteudo); // Obtem Input para receber dados utilizando o socket criado
                    
                    System.out.append(Arrays.toString(conteudo)); // Importe
                }
            }
            catch(UnknownHostException ex) { // Importe
                System.err.println("Host desconhecido!");
            }
            catch(IOException ex) { // Importe
                Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex); // Importe
            }
        } 
    }
    
    

    O lado servidor recebe o stream de bytes, ordena e devolve ao cliente, esse é o código do Servidor:

    
    package conexoes;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Arrays;
    
    public class Servidor {
        private Socket sock; // Importe
        
        public Servidor(Socket sock) {
            this.sock = sock;
        }
        
        public static void main(String[] args) {
            int porta = 33333; // Porta default (a mesma do cliente)
            
            try {
                ServerSocket servSock = new ServerSocket(porta); // Criamos o socket apenas com a porta, importe
                System.out.println("Socket criado!");
                
                while(true) { // Loop para receber comunicações de clientes
                    System.out.println("Aguardando cliente...");
                    
                    try(Socket clie = servSock.accept()) {
                        try(InputStream in = clie.getInputStream(); OutputStream out = clie.getOutputStream()) { // Importe
                            byte buffer[] = new byte[2048];
                            int n;
                            
                            while((n = in.read(buffer)) > 0) {
                                for(int i = 0; i < n; i++) {
                                    System.out.printf("%02d", buffer[i]);
                                }
                                
                                System.out.println(servSock.getInetAddress().toString());
                                
                                Arrays.sort(buffer, 0, n); // Ordena, importe
                                
                                out.write(buffer);
                            }
                        }
                        catch(IOException ex) {
                            System.err.println("Erro no accept: " + ex.getMessage());
                        }
                    }
                }
            }
            catch(IOException ex) {
                System.err.println(ex.getMessage());
            }
        }
    }
    
    

    Agora rode, não esqueça de fechar todas as conexões que usam a determinada porta.

    Sockets em Java - Parte 3

    Vamos fazer uma aplicação simples que funciona da seguinte maneira: O cliente cria um datagrama socket, um datagrama em pacote, recebe um pacote, obtém datae hora local e envia pacote para o emissor. O servidor recebe esse pacote.

    A classe servidor deverá ficar assim:

    
    package conexoes;
    
    import java.io.ByteArrayOutputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    import java.util.Date;
    
    public class Servidor {
        public static void main(String[] args) {
            int porta = 33333;
            
            // Vamos aceitar a porta como argumento do programa:
            if(args.length >= 1) {
                porta = Integer.valueOf(args[0]);
            }
            
            // Datagram sockeT indica que isto é UDP:
            
            DatagramSocket sock; // Importe
            
            try {
                sock = new DatagramSocket(porta);
                
                // Buffer criado para enviar ou receber dados:
                
                byte buffer[] = new byte[8];
                
                // Criação do datagrama pack:
                DatagramPacket pct = new DatagramPacket(buffer, buffer.length); // Importe
            
                // Espera e recebe um pacotecom a data no buffer:
                
                System.out.println("Esperando mensagem do cliente...");
                
                try {
                    sock.receive(pct);
                }
                catch(IOException ex) { // Importe
                    System.err.println("Erro: Recebimento de pacote!");
                }
                
                // Obter a data:           
                Date data = new Date(); // Importe
                
                // A melhor forma de escrever é utilizar streams, o socket lê isso:          
                ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Importe
                // E usamos em conjunto com isso:
                DataOutputStream dos = new DataOutputStream(baos); // Importe
                
                try {
                    dos.writeLong(data.getTime());
                } 
                catch(IOException ex) {
                    System.err.println("Erro: Conversão da data para o array!");
                }
                
                // Manda o pacote para o cliente, em pct tem o IP do cliente:
                System.out.println("Enviando data para cliente " + pct.getAddress());
                
                buffer = baos.toByteArray();
                pct = new DatagramPacket(buffer, buffer.length, pct.getAddress(), pct.getPort());
                
                try {
                    sock.send(pct);
                }
                catch(IOException ex) {
                    System.err.printf("Erro: Envio de pacote para %s.\n", pct.getAddress().toString());
                }
             
                System.out.printf("Pacote enviado para %s!\n", pct.getAddress().toString());
                System.out.printf("Data enviada: %s.\n", data.toString());
            }
            catch(SocketException ex) { // Importe
                System.err.println("Erro: Criação do socket!");
            }
        }
    }
    
    

    E no cliente:

    
    package conexoes;
    
    import java.io.ByteArrayInputStream;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.Date;
    
    public class Cliente {
        public static void main(String[] args) throws UnknownHostException {
            // Endereço do servidor:
            String serv = "127.0.0.1";
            int porta = 33333;
            
            if(args.length >= 1) {
                serv = args[0];
                
                if(args.length == 2) {
                    porta = Integer.valueOf(args[1]);
                }
            }
            
            try {
                // Criar datasocket:
                DatagramSocket sock = new DatagramSocket(); // Importe
                
                // Criamos um buffer para poder enviar ou receber dados:
                byte buffer[] = new byte[8];
                // Criar um endereço para enviar pacote ao servidor:
                InetAddress end = InetAddress.getByName(serv); // Importe e adicione o throws no método main
                // Criar um datagrama:
                DatagramPacket pct = new DatagramPacket(buffer, buffer.length, end, porta); // Importe
                // Enviamos um pacote em branco como mensagem para receber a data:
                System.out.printf("Enviando solicitação de data para %s.\n", end.toString());
                
                try {
                    sock.send(pct);
                }
                catch(IOException ex) {
                    System.err.println("Erro: Envio de mensagem para servidor!");
                }
                
                // Espera e recebe um pacote com a data no buffer:
                pct = new DatagramPacket(buffer, buffer.length);
                
                System.out.println("Aguardando data do servidor...");
                
                try {
                    sock.receive(pct);
                }
                catch(IOException ex) {
                    System.err.println("Erro: Recebimento de Mensagem do Servidor!");
                }
                
                // Decodificando, processo inverso do que vimos no servidor:
                DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buffer)); // Importe
                
                try {
                    Date data = new Date(dis.readLong()); // Isso converte a data, importe
                    
                    System.out.printf("Data recebida: %s.\n", data.toString());
                }
                catch(IOException ex) {
                    System.err.println("Erro: Conversão de data!");
                }
            }
            catch(SocketException ex) {
                System.err.println("Erro: Criação do socket!");
            }
        }
    }
    
    

    Execute a classe servidor e depois a cliente.