{"id":70,"date":"2024-09-20T13:57:43","date_gmt":"2024-09-20T16:57:43","guid":{"rendered":"https:\/\/tromineo.com.br\/blog\/?p=70"},"modified":"2026-03-16T22:30:54","modified_gmt":"2026-03-17T01:30:54","slug":"websockets-com-php","status":"publish","type":"post","link":"https:\/\/tromineo.com.br\/blog\/index.php\/2024\/09\/20\/websockets-com-php\/","title":{"rendered":"Websockets e Php, \u00e9 poss\u00edvel?"},"content":{"rendered":"\n<h2 class=\"wp-block-heading has-text-align-center\">O que s\u00e3o os famosos Websockets?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c9 um protocolo de comunica\u00e7\u00e3o na rede. Assim como o protocolo Http, o websocket permite que uma aplica\u00e7\u00e3o se comunique com outra por\u00e9m diferente do Http, a conex\u00e3o \u00e9 cont\u00ednua. Isso elimina a necessidade de iniciar uma nova conex\u00e3o com o servi\u00e7o\/servidor para nos comunicarmos com ele.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Uma analogia que pode ajudar a visualizar esse modelo de comunica\u00e7\u00e3o \u00e9 a seguinte: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine que voc\u00ea est\u00e1 chegando em um restaurante para almo\u00e7ar. Ao chegar no restaurante, \u00e9 abordado(a) por um gar\u00e7om que vai anotar e encaminhar o seu pedido \u00e0 cozinha. Assim que o pedido estiver pronto, o gar\u00e7om ir\u00e1 lev\u00e1-lo at\u00e9 voc\u00ea. Nesse exemplo, o gar\u00e7om representa o protocolo Http, onde toda vez que voc\u00ea necessitar de um recurso da cozinha, ser\u00e1 necess\u00e1rio que o gar\u00e7om realize um novo trajeto da sua mesa at\u00e9 a cozinha e vice-versa.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"724\" height=\"483\" src=\"https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/garcom.webp\" alt=\"\" class=\"wp-image-109\" srcset=\"https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/garcom.webp 724w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/garcom-300x200.webp 300w\" sizes=\"auto, (max-width: 724px) 100vw, 724px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Agora, imagine que no dia seguinte voc\u00ea foi a um restaurante diferente do anterior: esse n\u00e3o possui um funcion\u00e1rio que anota o seu pedido. Ao inv\u00e9s disso, utiliza um tablet por onde voc\u00ea registra um pedido e ele \u00e9 recebido pela cozinha. Caso queira fazer um novo pedido, pode acessar o tablet a qualquer momento e realiz\u00e1-lo, sem a necessidade do interm\u00e9dio do gar\u00e7om. Esse segundo exemplo se assemelha ao modelo de comunica\u00e7\u00e3o usando Websockets.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"940\" height=\"677\" src=\"https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/cardapio.jpg\" alt=\"\" class=\"wp-image-111\" srcset=\"https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/cardapio.jpg 940w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/cardapio-300x216.jpg 300w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/cardapio-768x553.jpg 768w\" sizes=\"auto, (max-width: 940px) 100vw, 940px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">Quando vou usar websockets ?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c9 muito comum usar esse tipo de comunica\u00e7\u00e3o quando estamos trabalhando em aplica\u00e7\u00f5es que precisam de um fluxo de comunica\u00e7\u00e3o ou troca de informa\u00e7\u00e3o constante, initerrupta ( &#8216;funcionam em tempo real&#8217;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aplica\u00e7\u00f5es como:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>P\u00e1ginas de email<\/strong>, onde assim que uma nova mensagem for recebida, precisa atualizar a lista de emails na tela;<\/li>\n\n\n\n<li><strong>Aplica\u00e7\u00f5es de chat<\/strong>, onde a mensagem enviada precisa ser recebida e visualizada;<\/li>\n\n\n\n<li><strong>Aplica\u00e7\u00e3o de alarme de seguran\u00e7a<\/strong>, onde a comunica\u00e7\u00e3o com uma central de controle \u00e9 constante para monitoramento de poss\u00edveis amea\u00e7as;<\/li>\n\n\n\n<li><strong>Aplica\u00e7\u00e3o para edi\u00e7\u00e3o de documentos compartilhados<\/strong>, onde mais de um usu\u00e1rio tem acesso ao mesmo recurso e as altera\u00e7\u00f5es devem ser visualizadas por eles.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Basicamente solu\u00e7\u00f5es que v\u00e3o enviar\/receber informa\u00e7\u00f5es constantes onde o modelo <em>Http n\u00e3o seria t\u00e3o eficiente (Imagina se para atualizar a lista de emails na tela fosse necess\u00e1rio iniciar uma nova conex\u00e3o com o servidor! Muitos recursos envolvidos). <\/em> <\/p>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">Como usar esse protocolo? <\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/media1.tenor.com\/m\/G5ZipVdTFBAAAAAd\/azealia-banks-so-what-now.gif\" alt=\"\"\/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Podemos criar uma aplica\u00e7\u00e3o que servir\u00e1 de servidor destino onde uma outra aplica\u00e7\u00e3o pode se conectar e se comunicar atrav\u00e9s de um WebSocket. E \u00e9 mais f\u00e1cil do que parece!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Em um novo diret\u00f3rio, vamos fazer o seguinte:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instalar o composer<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sS https:\/\/getcomposer.org\/installer | php<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">E, depois com o composer inicializado (<strong>composer<\/strong> ini) e o arquivo composer.json criado, vamos instalar o pacote <strong>cboden\/ratchet<\/strong>. Pra isso, basta rodar o comando:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>composer require cboden\/ratchet<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">O seu <strong>composer.json<\/strong> deve, ent\u00e3o, ficar assim:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"require\": {\n        \"cboden\/ratchet\": \"^0.4.4\"\n    }\n    ,\"autoload\": {\n        \"psr-4\": {\n            \"App\\\\\": \".\/\"\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Agora, vamos fazer o principal desenvolvimento: precisamos desenvolver uma <strong>classe<\/strong> que <strong>implementa uma interface<\/strong>. E s\u00f3! Bom&#8230;n\u00e3o \u00e9 <em>s\u00f3<\/em> isso. T\u00e9cnicamente <span style=\"text-decoration: underline;\">vamos desenvolver uma nova classe, ou um objeto, que implementa uma interface espec\u00edfica que indica quais os m\u00e9todos devem ser desenvolvidos na classe para que ela consiga produzir um canal de comunica\u00e7\u00e3o usando websockets<\/span>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nesse exemplo a classe vai se chamar <strong>WebServer<\/strong> e vamos cri\u00e1-la na ra\u00edz do projeto mesmo. Ela deve ficar assim:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nnamespace App;\nuse Ratchet\\MessageComponentInterface;\nuse Ratchet\\ConnectionInterface;\n\nclass WebServer implements MessageComponentInterface{\n    protected $clients;\n\n    public function __construct()\n    {\n        $this->clients = new \\SplObjectStorage;\n    }\n\n    public function onOpen(ConnectionInterface $conn) {\n        $this->clients->attach($conn);\n        echo \"Nova conex\u00e3o aberta: \".$conn->resourceId.\"\\n\";\n    }\n\n    public function onMessage(ConnectionInterface $from, $msg) {\n        echo \"Nova mensagem recebida:{$msg} - &#91;Id conex\u00e3o: {$from->resourceId}]\\n\";\n        \n        foreach($this->clients as $client) {\n            if($client != $from) {\n                $client->send($msg);\n            }\n        }\n    }\n\n    public function onClose(ConnectionInterface $conn) {\n        $this->clients->detach($conn);\n        echo \"Conex\u00e3o fechada: \".$conn->resourceId.\"\\n\";\n        \n    }\n\n    public function onError(ConnectionInterface $conn, \\Exception $e) {\n        echo \"Erro: \".$e->getMessage().\"\\n\";\n        $conn->close();\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Essa classe implementa os m\u00e9todos: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>onOpen<\/strong> -&gt; Chamado quando um novo cliente se conectar no servidor;<\/li>\n\n\n\n<li><strong>onMessage<\/strong> -&gt; Chamado quando uma nova mensagem for enviada no servidor;<\/li>\n\n\n\n<li><strong>onClose<\/strong> -&gt; Chamado quando um cliente se desconecta do servidor;<\/li>\n\n\n\n<li><strong>onError<\/strong> -&gt; Chamado quando o servidor lan\u00e7ar algum erro ou exce\u00e7\u00e3o.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Al\u00e9m de possuir um atributo do tipo cole\u00e7\u00e3o <strong>SplObjectStorage<\/strong>: uma estrutura de dados do da linguagem php para armazenar objetos, que \u00e9 inicializada no construtor da nossa classe. Esse atributo \u00e9 usado para gerenciar os <strong>clientes conectados<\/strong>. Ele permite anexar, desanexar e iterar sobre objetos, o que \u00e9 ideal para o caso de m\u00faltiplas conex\u00f5es WebSocket, onde cada cliente \u00e9 representado por um objeto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No construtor, com c\u00f3digo <code>new \\SplObjectStorage<\/code> inicializamos essa estrutura vazia para garantir que a classe comece com uma cole\u00e7\u00e3o de clientes pronta para ser manipulada. Sempre que um novo cliente se conecta, ele \u00e9 adicionado (com o m\u00e9todo <code><strong>attach<\/strong><\/code>) e, quando se desconecta, \u00e9 removido (com o m\u00e9todo <code><strong>detach<\/strong><\/code>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Com isso, temos uma classe que est\u00e1 pronta para receber &#8216;conex\u00f5es via websocket&#8217;. Pra testarmos isso vamos instanciar a nossa classe em um novo arquivo chamado <strong>servidor.php<\/strong> (tamb\u00e9m na ra\u00edz do projeto).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nrequire_once('vendor\/autoload.php');\n\nuse Ratchet\\Http\\HttpServer;\nuse Ratchet\\Server\\IoServer;\nuse Ratchet\\WebSocket\\WsServer;\n\nuse App\\WebServer; \/\/ Caso esteja no namespace App\n\n$servidor = IoServer::factory(\n    new HttpServer(\n        new WsServer(\n            new WebServer()\n        )\n    ), 8080);\n\necho \"Servidor websocket iniciado na porta 8080. Aguardando novas conex\u00f5es...\\n\";\n$servidor->run();\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Esse arquivo \u00e9 respons\u00e1vel por importar as bibliotecas do Ratchet necess\u00e1rias e \u00e9 com a ajuda delas que podemos disponiilizar esse servidor na porta <strong>8080<\/strong> para acesso na web:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\\Http\\HttpServer;<\/strong><\/li>\n\n\n\n<li><strong>\\Server\\IoServer<\/strong>;<\/li>\n\n\n\n<li><strong>\\WebSocket\\WsServer<\/strong>;<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Usamos o m\u00e9todo <em>factory<\/em> da classe <strong>IoServer<\/strong> que recebe, como primeiro par\u00e2metro, uma nova inst\u00e2ncia da classe <strong>HttpServer<\/strong> que, por sua vez, recebe uma nova inst\u00e2ncia da classe <strong>WsServer<\/strong> e ela, por ultimo, recebe uma nova inst\u00e2ncia da classe que criamos antes e, como segundo par\u00e2metro, recebe em qual porta o servidor deve funcionar (no nosso caso, deixamos na porta <strong>8080<\/strong>). O m\u00e9todo vai retornar um objeto que possui o m\u00e9todo <strong>run()<\/strong>. Fazemos ent\u00e3o uma chamada para esse m\u00e9todo <strong>run()<\/strong> para iniciarmos o servidor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Depois disso, precisamos executar o arquivo direto na linha de comando:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php servidor.php<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">E pronto! Temos um servidor, rodando localmente, pronto para receber novas conex\u00f5es de clientes usando o protocolo websocket! Por enquanto, s\u00f3 vamos ver a mensagem que configuramos l\u00e1 no <strong>servidor.php<\/strong> sendo apresentada no terminal mas isso \u00e9 porque ainda n\u00e3o conectamos nesse servidor que criamos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vamos ent\u00e3o criar um arquivo com um c\u00f3digo html e javascript que vai servir de cliente para que possamos conectar no servidor pelo navegador. Podemos chamar esse arquivo de index.html e criamos ele na ra\u00edz do projeto .<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;WebSocket Chat&lt;\/title&gt;\n    &lt;script src=\"https:\/\/code.jquery.com\/jquery-3.6.0.min.js\"&gt;&lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h2&gt;WebSocket Chat&lt;\/h2&gt;\n    &lt;input type=\"text\" id=\"message\" placeholder=\"Enter your message\"&gt;\n    &lt;button id=\"send\"&gt;Send&lt;\/button&gt;\n    &lt;div id=\"chat\"&gt;&lt;\/div&gt;\n\n    &lt;script&gt;\n        $(document).ready(function() {\n            var ws = new WebSocket('ws:\/\/localhost:8080');\n\n            \/\/ When receiving a message from the server\n            ws.onmessage = function(event) {\n                $('#chat').append('&lt;p&gt;' + event.data + '&lt;\/p&gt;');\n            };\n\n            \/\/ Sending a message to the server\n            $('#send').click(function() {\n                var msg = $('#message').val();\n                ws.send(msg);\n                $('#message').val('');\n            });\n        });\n    &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ao abrirmos esse arquivo no navegador em uma nova aba e uma aba an\u00f4nima podemos ver isso (a abertura em uma aba an\u00f4nima serve para que possamos visualizar as conex\u00f5es simult\u00e2neas e como o protocolo opera com elas).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"322\" src=\"https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/image-5-1024x322.png\" alt=\"\" class=\"wp-image-151\" srcset=\"https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/image-5-1024x322.png 1024w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/image-5-300x94.png 300w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/image-5-768x241.png 768w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/image-5-1536x483.png 1536w, https:\/\/tromineo.com.br\/blog\/wp-content\/uploads\/2024\/09\/image-5.png 1696w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclus\u00e3o<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WebSockets permitem comunica\u00e7\u00e3o bidirecional e em tempo real entre um ou mais clientes e o servidor. Ao contr\u00e1rio de requisi\u00e7\u00f5es HTTP tradicionais, onde o cliente sempre inicia a conex\u00e3o, os WebSockets permitem que o servidor tamb\u00e9m envie mensagens ao cliente sem que ele precise solicitar a todo momento e podem ser facilmente implementados na linguagem PHP com o aux\u00edlio do pacote Ratchet. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consegue pensar em mais aplica\u00e7\u00f5es interessantes usando esse protocolo? <\/p>\n","protected":false},"excerpt":{"rendered":"<p>O que s\u00e3o os famosos Websockets? \u00c9 um protocolo de comunica\u00e7\u00e3o na rede. Assim como o protocolo Http, o websocket permite que uma aplica\u00e7\u00e3o se comunique com outra por\u00e9m diferente do Http, a conex\u00e3o \u00e9 cont\u00ednua. Isso elimina a necessidade de iniciar uma nova conex\u00e3o com o servi\u00e7o\/servidor para nos comunicarmos com ele. Uma analogia [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28],"tags":[],"class_list":["post-70","post","type-post","status-publish","format-standard","hentry","category-php"],"_links":{"self":[{"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/posts\/70","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=70"}],"version-history":[{"count":28,"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/posts\/70\/revisions"}],"predecessor-version":[{"id":236,"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/posts\/70\/revisions\/236"}],"wp:attachment":[{"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=70"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=70"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tromineo.com.br\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=70"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}