Thiago Cantero

Tecnologia e Entretenimento

Desenvolvimento WebJavascriptlinguagem de programaçãoPHP

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:

WebSocket - Wikipedia
Figura obtida em https://en.wikipedia.org/wiki/WebSocket

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.

Cliente em aba normal
Cliente na Aba anônima, que recebeu a mensagem: “Envio de Mensagem”

 

Por fim recebe a mensagem: “Teste de Resposta”

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.