Programação com websockets
Olá, mundo!
Tudo bem?
Hoje iremos tratar sobre um assunto muito necessário, quando iremos implementar uma solução como um Chat em nossa aplicação. Falaremos sobre websockets.
Mas o que seria Websockets?
WebSocket é uma tecnologia que permite a comunicação bidirecional por canais full-duplex sobre um único soquete Transmission Control Protocol (TCP). Wikipedia – Websockets
Quando estamos realizando uma comunicação com um servidor, e precisamos de uma resposta, em um caso hipotético de uma aplicação de bate-papo, necessitamos a adoção de websockets. Esta comunicação é basicamente realizada por um cliente/servidor. No curso desta funcionalidade, há mensagens enviadas/recebidas de maneira bidirecional, e quando ela é fechada por um dos nós (Cliente ou Servidor), a conexão é fechada.
Veja o desenho abaixo:
Com este conceito bem definidos, façamos na prática.
Vamos ao trabalho\\
Como sempre estou desenvolvendo em PHP, faremos o exemplo em PHP, mas reforço que Java, C#, C++, NodeJS, Python, Ruby também tem suas bibliotecas de websockets. ; )
Primeiro vamos criar nossa pasta:
$ mkdir websockets
Após a criação dela, vamos criar os arquivos e a subpasta app/ :
$ touch index.html Chat.php composer.json $ mkdir app && cd app && touch Socket.php
Como criamos o arquivo Composer.json, agora vamos configurá-lo para baixar a extensão para PHP que fará o serviço de WebSocket, a Ratchet, um ponto importante!Estamos declarando a Namespace de nossa Inteface como “WebSockets”, que ficará na pasta app.
{ "autoload": { "psr-4": { "WebSockets\\": "app" } }, "require": { "cboden/ratchet": "^0.4" } }
Voltamos a raiz de nosso projeto e façamos a instalação dos pacotes:
$ composer install
Agora com a IDE que mais lhe agradar, e vamos para criação de nossa interface.
app/Socket.php
<?php namespace WebSockets; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; class Socket implements MessageComponentInterface { public function __construct() { $this->clients = new \SplObjectStorage; } public function onOpen(ConnectionInterface $conn) { // Armazena uma nova conexão $this->clients->attach($conn); echo "Nova Conexão! ({$conn->resourceId})\n"; } public function onMessage(ConnectionInterface $from, $msg) { foreach ( $this->clients as $client ) { if ( $from->resourceId == $client->resourceId ) { continue; } $client->send( "Usuário $from->resourceId disse $msg" ); } } public function onClose(ConnectionInterface $conn) { } public function onError(ConnectionInterface $conn, \Exception $e) { } }
Aqui temos nossa classe Abstrata que implementa uma Interface com a biblioteca de Sockets.
Vejamos abaixo o que cada método faz:
Temos um método construtor que terá a responsabilidade de instanciar o objeto, que em nosso caso será a conexão por websockets.
onOpen() – Criará uma nova conexão, quando um cliente abrir a página, atribuirá a ele um número e salvará na variável $clients.
onMessage() – Fará o envio das mensagens entre os clientes que estarão com as conexões ativas.
onClose() – Fechará a conexão quando um ou mais clientes não estiveram mais utilizando o serviço.
onError() – Em nosso caso será uma exceção disparada, caso haja algum erro.
Agora devemos criar nosso Servidor que fará as requisições entre os clientes.
Chat.php
<?php use Ratchet\Server\IoServer; use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; use WebSockets\Socket; require dirname( __FILE__ ) . '/vendor/autoload.php'; $server = IoServer::factory( new HttpServer( new WsServer( new Socket() ) ), 8080 ); $server->run();
Na variável $server ele faz a chamada da classe IoServer, e aplicando o método factory, instancia um novo servidor HttpServer que terá um WebsocketServer atribuído na porta 8080.
Por fim, vamos criar nosso Cliente que servirá para enviarmos a mensagem entre os usuários.
Index.html
<!DOCTYPE html> <html lang="pt-br"> <head> <title>WebSockets com PHP</title> <style> input, button { padding: 10px; } </style> <meta charset="utf-8"> </head> <body> <input type="text" id="mensagem" /> <button onclick="enviarMensagem()">Enviar</button> <script> // Cria um novo WebSocket var socket = new WebSocket('ws://localhost:8080'); // Pega o elemento da Div HTML var mensagem = document.getElementById('mensagem'); function enviarMensagem() { socket.send( mensagem.value ); } socket.onmessage = function(e) { alert( e.data ); } </script> </body> </html>
Nossa página terá embutido no HTML uma função em javascript para envio de mensagem enviarMensagem() que dentro dela irá criar um novo Websocket na porta 8080, pegar a mensagem no formulário e enviar a mensagem para o outro cliente, através de um alert.
Para fazer funcionar, vamos executar o Chat.php no console.
$ php Chat.php
Abri uma janela em aba normal e outra na aba anônima para criar o conceito de duas sessões distintas, e assim simular o nosso Chat.
Com isso terminamos nosso Chat, e aplicamos na prática o conceito. É possível trabalhar com banco de dados para armazenamento de mensagens, neste caso recomendo um banco não relacional, como mongodb.
Por hoje é só.
Até a próxima. ; )
Não tentes ser bem-sucedido, tenta antes ser um homem de valor.