O Websocket  é um protocolo que nos permite abrir uma comunicação bidirecional com o servidor utilizando um único soquete TCP (Transmission Control Protocol) através do navegador. Sendo assim, tanto o cliente quanto o servidor podem enviar informações entre si a qualquer momento. Neste artigo, veremos como implementar um simples aplicativo de chat utilizando este protocolo.

No lado cliente utilizaremos o Vue.JS para facilitar a construção da interface do chat, além de manter um código mais organizado.

No lado servidor utilizaremos o Ratchet que é uma biblioteca PHP que nos permite construir um servidor de Websocket de um jeito descomplicado.

Confira o exemplo em funcionamento, clicando aqui.

O lado servidor

Primeiramente, precisamos importar a biblioteca do Ratchet para nosso projeto. Para isso iremos utilizar o Composer. Portanto, vamos criar nosso composer.json.

Basta agora rodar composer install no terminal e podemos começar. Vamos então criar a classe que será responsável por gerenciar as conexões recebidas.

Criamos a propriedade $clients que será responsável por armazenar as conexões recebidas. Cada conexão é um objeto do tipo ConnectionInterface disponibilizado pela biblioteca, portanto utilizamos um SplObjectStorage , pois possui algumas vantagens além de um desempenho melhor para armazenamento de objetos. Através do método send() do objeto de conexão, conseguimos enviar as informações para o lado cliente.

Pronto, agora que já temos a classe, basta criar o arquivo que irá iniciar o servidor para aguardar as conexões.

Basicamente, inicia o servidor de Websocket, que passará a receber conexões na porta 8080.

Agora precisamos executar este arquivo para iniciar nosso servidor de Websocket. Para isso você precisa ir até o terminal, navegar até a pasta dele e executar o comando abaixo.

Pronto, agora nosso servidor de Websocket foi iniciado e está apenas aguardando as conexões, precisamos agora então criar o lado cliente.

O lado cliente

Javascript

Vamos iniciar o aplicativo do Vue que será responsável por gerenciar nossa página. Caso você nunca tenha utilizado o Vue, recomendo a leitura do guia oficial do framework.

  • Linha 4: Definimos que o escopo do nosso aplicativo será o elemento que tenha o id igual à app. Dentro deste elemento poderemos acessar as propriedades e métodos que veremos a seguir.
  • Linha 7 até 12: Definimos as propriedades do nosso aplicativo.
    • user: nome de usuário que está conectado;
    • text: mensagem atual do usuário;
    • messages: lista com todas as mensagens recebidas;
    • ws: objeto que irá armazenar a conexão com o Websocket;
  • Linha 29: Criamos um novo objeto de conexão com base nas informações de nosso servidor.
  • Linha 47: Os dados recebidos são apenas texto, porém para conseguirmos interpretar as informações, vamos utilizar o formato JSON, portanto convertemos os dados recebidos utilizando JSON.parse() e passamos para o método addMessage() que criaremos adiante.
  • Linha 53 até 56: Adiciona a mensagem na propriedade messages e o Vue vai se encarregar de atualizar a página para nós. Além disso chamamos o método scrollDown() para rolar o scroll das mensagens para baixo para que o usuário possa acompanhá-las.
  • Linha 80: Através da propriedade readyState do objeto do Websocket, conseguimos saber o status da conexão que pode ser: CONNECTING, OPEN, CLOSING e CLOSED.
  • Linha 87 até 89: Como a conexão não está aberta, chamamos o método de conexão novamente, porém passamos como parâmetro uma função (callback) que será chamada após a conexão ser realizada, enviando a mensagem novamente para que o usuário não tenha que pressionar enter de novo.
  • Linha 96 até 99: Os dados enviados chegarão no servidor no formato texto, portanto convertemos o JSON para texto utilizando JSON.stringify() e enviamos para o servidor através do método send() do Websocket.
  • Linha 107 até 110: Buscamos o elemento que contém as mensagens através do querySelector() e definimos que a posição do scroll é o tamanho dele. Na prática, rola o scroll até o fim.

HTML

  • Linha 7: v-cloak nos permite esconder o elemento até o framework ter sido completamente carregado, pois caso contrário você verá a página do jeito que está por alguns segundos até o carregamento completo do framework.
  • Linha 8: v-for nos permite repetir um elemento de acordo com uma collection. No caso, iremos repetir o elemento li (item da lista) para cada item da propriedade messages.
  • Linha 9 e 10:  O v-if nos permite definir se um elemento será criado ou não através de uma condição. Neste caso, se a propriedade não existir no objeto message, não exibiremos o elemento. Este teste é necessário pois as notificações de sucesso e erro não possuem data e usuário. Por fim, através das {{ }} exibimos o valor da propriedade.
  • Linha 11: O :style (ou v-bind:style) nos permite definir uma propriedade CSS dinamicamente. No caso, vamos definir a cor do texto de acordo com a propriedade color do objeto message, pois definimos no aplicativo que a notificação de sucesso será green e de erro red.
  • Linha 26 e 27: O v-model nos permite vincular um campo de formulário com uma propriedade, sendo assim sempre que o campo for atualizado, a propriedade será atualizada e vice-versa. O @keyup (ou v-on:keyup) nos permite chamar um método quando uma tecla for pressionada, no caso definimos que no enter chamaremos o método sendMessage() para enviar a mensagem.

Hospedagem

Se você seguiu os passos acima, provavelmente o aplicativo deve estar funcionando localmente na sua máquina. Porém, como você faria para ele funcionar em um serviço de hospedagem?

Primeiramente, se você utiliza algum serviço de hospedagem compartilhada, dificilmente você vai conseguir subir o aplicativo lá, pois para que de certo você terá que ter acesso ao servidor via SSH (Secure Shell).

Supondo que você tenha acesso via SSH, basta enviar os arquivos e então executar o comando para iniciar o servidor, da mesma forma que você fez localmente.

Lembre-se que a porta 8080 deve estar aberta para acesso externo, portanto, se necessário, você deve liberá-la no firewall e roteador.

No lado cliente, você terá que trocar o localhost pelo endereço do seu servidor, por exemplo, ws://rafaelcouto.com.br:8080. Feito isso, tudo deveria funcionar normalmente. Porém, quando você fechar a conexão SSH, o servidor irá parar a execução; para evitar isso, você precisa criar um serviço. Você pode fazer isso da seguinte maneira:

  • 1) Navegar até /etc/init: cd /etc/init
  • 2) Criar o arquivo chatsocket.conf: sudo nano chatsocket.conf
  • 3) Colocar o conteúdo abaixo no arquivo, trocando “/path/to/server.php” pelo caminho real do arquivo server.php no seu servidor e então salvar.

Pronto, agora você pode iniciar o serviço através do comando service chatsocket start ,  fechar a conexão SSH e o servidor de Websocket continuará sendo executado.

Conclusão

Neste artigo vimos como implementar um simples chat utilizando Websocket com PHP. O Ratchet facilita muito a implementação do servidor bastando apenas criar uma classe e implementar os eventos disponibilizados pela biblioteca.

Existem diversas técnicas para simular uma aplicação em tempo real, como o Long Polling e Server-sent Event, porém nenhuma delas proporciona uma comunicação bidirecional real e de baixa latência como o Websocket.

Vimos a possibilidade de criar um aplicativo de chat, porém o Websocket não se limita apenas a isso. Você pode utilizar o mesmo conceito para qualquer aplicativo que precise receber e/ou enviar informações em tempo real.

Enfim, espero que este artigo tenha sido útil de alguma forma para você e que você possa começar a utilizar o Websocket para criação de aplicativos em tempo real.

Código fonte disponível em: https://github.com/rafaelcouto/Post1652

Referências

Compartilhe
Share on Facebook0Share on Google+0Tweet about this on TwitterPin on Pinterest0Email this to someone