Escolar Documentos
Profissional Documentos
Cultura Documentos
Título: Nº de Páginas: 07
Utilização da biblioteca socket.io para implementação de comunicação
bidirecional Websocket entre um Servidor Web e uma Página Web Cliente.
Objetivo/Resumo:
Esta NT documenta a implementação de um Webserver com os protocolos HTTP e Websocket em
Python, e de uma página cliente em HTML e Javascript com comunicação bidirecional utilizando as
implementações da biblioteca socket.io em Python e Javascript.
Autores: Palavras-Chave:
André Tomaz de Carvalho GAMMA, socketio, Python, HTTP, Javascript,
websockets, webserver.
Classificação de acesso:
E-mail: tomaz@cepel.br
C e n t r o d e P e s q u i s a s d e E n e r g i a E l é t r i c a – C E P E L www.cepel.br
Sede: Av. Horácio Macedo, 354 - Cidade Universitária - CEP 21941-911 - Rio de Janeiro - RJ - Brasil - Tel.: 21 2598-6000
Unidade Adrianópolis: Av. Olinda, 5800 - Adrianópolis - CEP 26053-121 - Nova Iguaçu - RJ - Brasil - Tel.: 21 2666-6200
Endereço Postal: CEPEL Caixa Postal 68007 - CEP 21941-971 - Rio de Janeiro - RJ - Brasil / Endereço Eletrônico: cepel@cepel.br
1. Introdução
Esta NT descreve como o servidor de HTTP e essa troca bidirecional de mensagens podem ser
implementados a partir das bibliotecas homônimas socketio para Python [2] e socketio para
Javascript [3].
GET
http server html
Webserver Navegador
import eventlet
import socketio
sio = socketio.Server()
app = socketio.WSGIApp(sio, static_files={
'/': {'filename': 'index.html'},
'/socket.io.js': {'filename': 'socket.io.js'},
______________________________________________________________________________
2/7
F-CO-014, REV. 0, 04/10/2021
if __name__ == '__main__':
eventlet.wsgi.server(eventlet.listen(('localhost', 5000)), app)
Fig. 2 – Implementação de um servidor estático de HTTP com socketio.
O método socketio.WSGIApp() recebe como parâmetro uma estrutura que, a cada caminho
apontado na URL do navegador (‘/’, ou ‘/socket.io.js’, por exemplo), associa quais arquivos
devem ser enviados ao navegador.
Essa lista é um dicionário que pode ser usado para rotear solicitações, isto é, posso enviar um
arquivo com outro nome diferente daquele solicitado na URL.
Ao definir essa lista arquivo por arquivo, todos os arquivos de interesse devem ser incluídos,
incluindo scrips e css. No caso da Fig. 2, como não foi definido uma página para o caminho
http://127.0.0.1:5000/index.html, o servidor retorna uma mensagem ‘not found’. A página
index.html só é enviada se o usuário acessar simplesmente http://127.0.0.1:5000.
Também é possível definir em uma única regra todos os arquivos de uma pasta como estáticos
fazendo, por exemplo:
static_files = {
'/static': './public',
}
Fig. 4 – Definição de todos os arquivos de uma pasta no servidor estático.
Nesse caso, todas as URLs começando com /static/*** retornarão os arquivos de nome ***
contidos na pasta ./public.
______________________________________________________________________________
3/7
F-CO-014, REV. 0, 04/10/2021
O protocolo Websocket estabelece uma conexão bidirecional de dados entre dois endpoints. O
servidor fica disponível para aceitar conexões de clientes que, uma vez conectados, podem
trocar mensagens com a aplicação.
Toda a API do socketio é baseada em eventos. Assim, o código abaixo define o tratamento de
três eventos distintos:
No código da Fig. 5, ao receber um evento de nome ‘echo’, o servidor emite uma mensagem
de retorno, isto é, emite um evento de nome 'clientReceiveTextMessage', retornando ao cliente
os dados enviados.
import eventlet
import socketio
sio = socketio.Server()
app = socketio.WSGIApp(sio, static_files={
'/': {'filename': 'index.html'},
'/socket.io.js': {'filename': 'socket.io.js'},
'/socket.io.js.map': {'filename': 'socket.io.js.map'},
'/wsClient.js': {'filename': 'wsClient.js'}
}
)
@sio.event
def connect(sid, environ): # Executa ao abrir uma conexão
print('connected to ', sid)
@sio.event
def disconnect(sid): # Executa ao fechar uma conexão
print('disconnect ', sid)
@sio.event
def echo(sid, data): # Executa ao receber um evento echo
sio.emit('clientReceiveTextMessage', 'Echoed message: ' + data) # Emite evento de
volta
print('Echoing Message: ', data)
______________________________________________________________________________
4/7
F-CO-014, REV. 0, 04/10/2021
if __name__ == '__main__':
eventlet.wsgi.server(eventlet.listen(('localhost', 5000)), app)
Fig. 5 – Código do Servidor de Websocket.
Desejamos que uma Página Web possa trocar dados com o servidor. Usaremos como exemplo
a página cujo código HTML pode ser visto na Fig. 6.
<!DOCTYPE html>
<html>
<head>
<title>Socket.io WS Client</title>
<style>
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system,
BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
</head>
<body>
<ul id="messages"></ul>
<div id="form">
<input id="input" autocomplete="off">
<button id="send">Send</button>
</div>
</body>
</html>
Fig. 6 – Código da página index.html.
A página é extremamente simples. Na seção <head> possui definições de estilo CSS, e faz
referência a dois scripts. Na seção <body> define uma lista <ul>, um <input> de texto e um
<button>.
SendMessageButton = document.getElementById("send").addEventListener("click",
sendMessage);
function sendMessage(){
socket.emit("echo", document.getElementById("input").value);
}
socket = io("ws://127.0.0.1:5000")
estabelece a conexão com o servidor. Caso a conexão não seja estabelecida ou seja
interrompida, o socketio tenta se reconectar automaticamente sucessivas vezes até obter
sucesso.
socket.emit(event, data);
é utilizado.
A Fig. 8 mostra o frontend da aplicação, que recebe do servidor mensagens de eco para todas
as mensagens enviadas.
______________________________________________________________________________
6/7
F-CO-014, REV. 0, 04/10/2021
5. Referências
[1] Nota Técnica DGA 1069/23 - Prototipação de Aplicações Simples com HTML e Javascript.
______________________________________________________________________________
7/7
F-CO-014, REV. 0, 04/10/2021