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.