Sockets: Vamos programar um servidor que diz as horas

26 Comentários

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.

sockets_02


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.

sockets_01

 

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

servidor5

Código fonte do Cliente

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

servidor2

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

servidor3

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

servidor4

[CLIENTE]

Agora é a vez de tratar do cliente. Para proceder à compilação do ficheiro devem usar o comando

javac Cliente.java

cliente2

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.

cliente3

E aqui está o resultado,

cliente4

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.

Comentários

26

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

  1. Avatar de jedi
    jedi

    também podes utilizar sockets através do html5 ( websockts.) 😉

    http://www.html5rocks.com/en/tutorials/websockets/basics/

    1. Avatar de zee
      zee

      Onde disseste Html5, deverias ter dito javascript. 🙂

      1. Avatar de apache
        apache

        Nem é HTML5, nem é JavaScript. É um protocolo que corre sobre TCP/IP que é inicializado através de uma conexão HTTP.

        1. Avatar de zee
          zee

          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.

          1. Avatar de joao
            joao

            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.

        2. Avatar de zee
          zee

          Quando digo ‘implementado’ no meu comentário, refiro-me à implementação do link que o jedi postou.

  2. Avatar de M3mn0t
    M3mn0t

    Muito simples, mas muito intuitivo. Continuem com este tipo de iniciativa.

  3. Avatar de zee
    zee

    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

    1. Avatar de Pedro Pinto

      Boa, obrigado. Tens toda a razão.

      PP

    2. Avatar de Bruno
      Bruno

      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.

      1. Avatar de zee
        zee

        Yup. Mas só está disponível na versão 8 do java.

        1. Avatar de Bruno
      2. Avatar de zee
        zee

        Tal como as expressões lambda, por exemplo.

        1. Avatar de Bruno
          Bruno

          lambda versão 8. Try-with-resources versão 7.

      3. Avatar de zee
        zee

        Afinal enganei-me. O try-with-resources está disponível a partir da versão 7.

        1. Avatar de Bruno
          Bruno

          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.

          1. Avatar de Pedro
            Pedro

            Boas Bruno

            Refaz aí o código que eu actualizo.

            Abraço
            Pp

  4. Avatar de Xinuo
    Xinuo

    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.

  5. Avatar de apache
    apache

    “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!

    1. Avatar de Fork
      Fork

      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!

      1. Avatar de Xinuo
        Xinuo

        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.

      2. Avatar de apache
        apache

        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…

  6. Avatar de Hugo Durana
    Hugo Durana

    Muito boa a iniciativa, continuem assim

  7. Avatar de Carlos Abreu
    Carlos Abreu

    Continuem com este tipo de iniciativas!

  8. Avatar de Gilberto Moraes
    Gilberto Moraes

    O exemplo mostra Linux conversando com Linux. Existe alguma diferença se for Linux conversando com Windows?