Neste post vamos entender um pouco sobre recursividade. Para isto eu fiz um vídeo que faz uma rápida apresentação do assunto e mostra como esta técnica pode ser empregada para resolver três diferentes problemas de computação:
Como calcular o fatorial de um número inteiro positivo;
Como resolver o problema do quebra cabeças denominado Torre de Hanói; e
Como gerar uma sequência de Fibonacci.
Vamos ao vídeo
Vamos calcular o fatorial
Vamos calcular a sequência de Fibonacci
Vamos resolver o problema da Torre de Hanói
Veja como construi esta classe. Coloquei no final os atributos e o método estático main() está no início da classe. Normalmente não utilizo este formato, mas ele ajuda a destacar a entrada da operação da classe.
No próximo post abre este assunto vamos ver um algoritmo de ordenação de dados que utiliza recursividade e também por ser muito eficiente é utilizado como algoritmo padrão em diversas linguagens inclusive o Java - estou falando do mergesort.
Vamos ver agora como ficou nossa classe. O funcionamento básico do programa pode ser descrito como:
Em main(), criamos uma instância de java.net.ServerSocket utilizando o socket localhost:61666. A porta 61666 pode ser alterada via argumento na linha de comando. Este socket permite que os clientes possam tentar conectar com o servidor.
colocamos um loop contínuo (sem saída) onde
verificamos se existe uma requisição de conexão verificando ServerSocket.accept(), quando existe este método retorna um socket denominado conexao
criamos uma thread que recebe o socket conexao como parâmetro de passagem
dentro da thread (método run()) criamos duas instâncias
entrada: que permite receber as mensagens enviadas pelo cliente
saida: que permite enviar mensagens para o cliente
esperamos que a primeira mensagem contenha o nome do usuário usando
usuario = entrada.readLine()
comparamos este nome enviado com os nomes guardados na lista clientesLogados
se existir, manda mensagem de erro
se não existir, coloca o nome na lista clientesLogados e entra em loop até receber uma mensagem /sair
No próximo post veremos um exemplo de uma classe cliente usando Socket.
Para podermos nos comunicar vamos ter que criar primeiro a nossa classe servidora do chat. Ela irá rodar no nosso servidor principal, receberá as conexões dos clientes e fará a comunicação entre eles. Para entender melhor o funcionamento deste servidor, precisamos conhecer o que é um socket e um servidor.
A definição de socket é um ponto de conexão em um link de comunicação de mão dupla entre dois programas rodando na rede, este socket é caracterizada pelo endereço IP e a porta que a aplicação verifica. Toda conexão TCP é identificada unicamente por estes dois parâmetros. Vamos ver como esta comunicação funciona:
a) O servidor fica rodando e escutando o socket (porta) esperando por uma requisição de conexão de um cliente. (isto equivalente a dizer que ele fica em um loop sem fim como veremos no programa)
b) Já o cliente, deve conhecer o socket que irá conectar (endereço e porta do servidor). Para conectar o cliente realiza uma comunicação com o servidor na porta determinada, devendo se identificar para o servidor.
c) O servidor ao receber e autorizar a conexão, armazena a porta e endereço de onde vem a comunicação do cliente e mapeia este socket do cliente com o canal de comunicação. No nosso exemplo, usamos o nome do usuário que é enviando na mensagem de requisição para mapear com o scocket do cliente - criamos um hashmap com estas duas informações
d) Tendo o servidor aceitado a conexão, ele cria um novo socket para realizar a comunicação. Através deste socket o servidor consegue falar com o cliente.
e) Já no lado do cliente, se a conexão é aceita, o socket (do cliente) é criado com sucesso. O cliente pode agora utilizar este socket para comunicar com o servidor.
OBS: O servidor continuar continua esperando novas conexões pelo socket do servidor.
A comunicação é feita mediante a leitura ou escrita no socket. O vídeo abaixo representa este processo