Sockets: Vamos programar um servidor que diz as horas
Quem gosta de tecnologia certamente já se questionou como determinados sistemas funcionam e comunicam. Hoje em dia, graças a adopção, como standard, do protocolo IP os dispositivos conseguem facilmente “comunicar” entre eles de uma forma totalmente transparente para o utilizador.
Hoje vamos ensinar como podem programar um simples servidor que informa as horas aos clientes que solicitem.
O que são sockets?
Actualmente existem algumas tecnologias que permitem a comunicação entre máquinas. Uma das tecnologias/mecanismos mais comuns para comunicação entre máquinas são os sockets.
Socket é um mecanismo de comunicação usado normalmente para implementar um modelo cliente/servidor, que permite a troca de mensagens entre os processos de uma máquina/aplicação servidor e de uma máquina/aplicação cliente – Saber mais aqui.
Como podemos ver pela imagem seguinte, para este modelo de comunicação haverá um servidor e um cliente. O servidor será iniciado e ficará à espera de pedidos dos clientes num porto específico.
Depois o cliente estabelece a ligação (usando o IP do servidor e porto) e, se tudo correr bem, o cliente e servidor passam a trocar informações entre eles.
No final da troca de mensagens, o cliente e o servidor fecham a comunicação.
Desenvolvimento de app cliente/servidor em Java
Programar uma aplicação cliente e servidor não é difícil e podemos sempre aproveitar muito do código partilhado (gentilmente) por muitos programadores. A aplicação servidor e cliente que propomos, foi desenvolvida em Java, nesse sentido o utilizador (para este tutorial) apenas necessita de ter o Java instalado e um editor de texto.
Na prática o servidor vai receber pedidos dos clientes, num porto específico e vai-lhes responder com as horas do sistema.
Pré-Requisitos
- Para que tudo funcione devem ter o java instalado
- Um editor de texto (opcional)
Nota: Para este tutorial vamos recorrer ao Xubuntu.
Para instalar a versão que pretendemos do java basta abrir o terminal e inserir o seguinte comando:
sudo apt-get install default-jdk |
Caso pretendam instalar um editor de texto básico como o gedit, usem o seguinte comando:
sudo apt-get install gedit |
Depois abram o gedit e copiem o seguinte código para o servidor e para o cliente. Assim devem criar dois ficheiros Servidor.java e Cliente.java
Código fonte do Servidor
Código fonte do Cliente
Nota: Caso tenham alguma dúvida na interpretação do código deem-nos essa indicação nos comentários.
Em seguida devem ir à linha de comandos do Linux, posicionar na pasta onde têm os ficheiros criados anteriormente e proceder à compilação dos mesmos. Iniciem pelo servidor.
[SERVIDOR]
javac Servidor.java |
O ficheiro compilado é designado de ByteCode, passando este a ser interpretado pela Java Virtual Machine. Para executar o ficheiro já compilado usem o seguinte comando:
java Servidor |
Para testarem se tudo está a funcionar, podem por exemplo fazer um telnet para o porto que está agora à espera de ligações. Para isso, basta que executem o seguinte comando a partir da própria máquina:
telnet 127.0.0.1 65333 |
[CLIENTE]
Agora é a vez de tratar do cliente. Para proceder à compilação do ficheiro devem usar o comando
javac Cliente.java |
Para executar o ficheiro já compilado usem o seguinte comando:
java Cliente |
Para começar introduzimos o endereço IP do servidor e carreguem em OK
Nota: Caso o cliente esteja a ser executado noutra máquina diferente do servidor, devem indicar o endereço que está atribuído à placa de rede do servidor.
E aqui está o resultado,
Como referimos, caso pretendam algum esclarecimento relativamente ao código disponibilizado, deixem esse pedido nos comentários. Na prática, a aplicação servidor implementa um ciclo while infinito, possibilitando desta forma que o servidor esteja sempre à espera de ligações. Por cada cliente que se ligue, é criado um socket e os streams de comunicação (de output e input).
Do lado do cliente apenas é estabelecida uma comunicação para o servidor, tendo em conta o IP deste e para o porto no qual está à escuta.
Download
Download:Sockets
Este artigo tem mais de um ano
também podes utilizar sockets através do html5 ( websockts.) 😉
http://www.html5rocks.com/en/tutorials/websockets/basics/
Onde disseste Html5, deverias ter dito javascript. 🙂
Nem é HTML5, nem é JavaScript. É um protocolo que corre sobre TCP/IP que é inicializado através de uma conexão HTTP.
Não disse que Websockets eram javascript. Disse sim que o protocolo é implementado em javascript. Não em HTML. Html é apenas uma linguagem de marcação.
Zee, precisas dum browser html5 compatível para o executar. Penso que seja isso a que o jedi se refere, embora possas usar sem ser num browser pois é um protocolo, logo a resposta correcta é a do apache.
Quando digo ‘implementado’ no meu comentário, refiro-me à implementação do link que o jedi postou.
Muito simples, mas muito intuitivo. Continuem com este tipo de iniciativa.
Grande iniciativa Pedro Pinto 🙂
Já agora, um reparo. O objecto PrintWriter também implementa a interface ‘Closeable’, portanto, faltaria fechar o mesmo (código do servidor). A seguir ao print, faltaria ‘out.close();’., para limpar os recursos associados ao printwriter. Sei que neste caso em específico não é algo que seja preocupante. Mas o meu comentário é no sentido de completar o artigo.
Cumprimentos
Boa, obrigado. Tens toda a razão.
PP
Na verdade existe uma forma mais prática. Usa-se o try-with-resources:
try(PrintWriter out = new PrintWriter(socket.getOutPutStream(),true)){
out.println(….);
}
Desta forma, não nos preocupamos com o out.close(), é feito automáticamente.
Yup. Mas só está disponível na versão 8 do java.
versão 7.
Tal como as expressões lambda, por exemplo.
lambda versão 8. Try-with-resources versão 7.
Afinal enganei-me. O try-with-resources está disponível a partir da versão 7.
Sim, e não querendo criticar a iniciativa, muito pelo contrário, o swing já foi descontinuado há alguns anos. Devemos usar o javafx, a aposta da oracle no presente e para o futuro.
Boas Bruno
Refaz aí o código que eu actualizo.
Abraço
Pp
Faltou um linha de import no código do servidor, creio que não aparece no print da tela, pois ficou escondida.
import java.io.IOException;
Deveriam ter cortado o rodapé da janela, ou melhor, deveria haver links com os fontes para baixar facilmente. Se bem que, para iniciantes, é bom digitar mesmo.
“Servidor” java da treta!
Era muito mais simples e reutilizável vocês usarem o xinetd (por exemplo):
service ppltime {
disable = no
socket_type = stream
port = 65333
…
user = pi (ou o que quiserem)
server = /bin/date
}
E pronto. Sim, cria um processo por cada conexão, que é como Deus quis, mas um utilizador não pode deitar o servidor inteiro abaixo!
Ó!
Mil clientes e CABUM ! Não escala esse modelo 😀
Se gostas desse tipo de paradigma eu sugeria dares uma vista de olhos no Modelo de Atores, que é o que o WhatsApp usa e é impressionante como conseguem manter um serviço destes com menos de 50 engenheiros!
Cono assim não escala! O comando date com certeza vai se mais rápido, ocupar menos memória, em fim, pesar menos para o SO. Mas o objetivo do post não é resolver o problema de maneira ótima, mas ensinar como utilizar sockets num programa.
CABUM nada!
Com o xinetd, podes limitar o número de clientes simultâneos, o número de conexões por segundo, etc.
Aposto que abrir um processo nativo Linux, e correr código… C… é mais rápido que correr um servidor multithreaded Java (que esse exemplo, não é), já para não falar que tens que implementar rate limiting e etc. à mão!!!
Eu sei o que é o modelo de actores, já programei várias coisas em node.js, mas lá está depende de quantos clientes tens, e de quanto tempo tens para o projeto, das tuas necessidades de alterar o código, etc…
Muito boa a iniciativa, continuem assim
Continuem com este tipo de iniciativas!
O exemplo mostra Linux conversando com Linux. Existe alguma diferença se for Linux conversando com Windows?