Vamos ver como configurar a comunicação entre um servidor e um cliente usando o protocolo Websockets em Python. O WebSockets é um protocolo de comunicação web simples e robusto para comunicação em tempo real.
Instalando a biblioteca Websockets
Para utilizar WebSockets com Python, instalamos o pacote necessário…
python3 -m pip install websockets
Também usamos a biblioteca asyncio, que permite a programação assíncrona para o desenvolvimento de servidores de alto desempenho.
Recuperar o endereço IP do servidor
Como em todas as comunicações na Internet, para estabelecer uma ligação entre o cliente e o servidor, é necessário conhecer o endereço IP do servidor.
Para obter o endereço IP da máquina do servidor, pode utilizar os comandos ipconfig (Windows) ou ifconfig/ ip addr (Linux) (aqui: 192.168.1.59).
Também pode utilizar o pacote socket no script Python
def getIpAddress(): import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ipaddress = s.getsockname()[0] s.close() return ipaddress ipaddress = getIpAddress()
Tome nota do endereço, que será utilizado no código de cliente.
Código Python para o servidor WebSocket
Para lançar o servidor, definimos uma função principal que abrirá o servidor na porta 8765 e o executará em um loop. Também chamamos a função de retorno de chamada echo(), que tratará da receção da mensagem. Neste exemplo, devolvemos a mensagem tal como está para o cliente.
#!/usr/bin/env python # python3 -m pip install websockets import asyncio from websockets.server import serve def getIpAddress(): import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ipaddress = s.getsockname()[0] s.close() return ipaddress ipaddress = getIpAddress() port = 8765 async def echo(websocket): async for message in websocket: print("received from {}:{} : ".format(websocket.remote_address[0],websocket.remote_address[1]) + message) await websocket.send(message) async def main(): print("Server is activated on ws://{}:{}".format(ipaddress,port)) #async with serve(echo, "localhost", 8765): async with serve(echo, "0.0.0.0", port): await asyncio.Future() # run forever asyncio.run(main())
Nota: para que o servidor seja visível na rede fora do computador, é necessário especificar o endereço “0.0.0.0” em vez de “localhost”.
Código Python para o cliente WebSocket
No código do cliente, ligamo-nos ao servidor especificando o endereço IP e a porta. De seguida, enviamos uma mensagem. Por fim, aguardamos que a mensagem de resposta seja apresentada.
#!/usr/bin/env python # python3 -m pip install websockets import asyncio from websockets.sync.client import connect def hello(): #with connect("ws://localhost:8765") as websocket: with connect("ws://192.168.1.52:8765") as websocket: websocket.send("Hello world!") message = websocket.recv() print(f"Received from server : {message}") hello()
Resultados
Em um terminal, primeiro execute o script do servidor: python websocket_server.py
Num segundo terminal, execute o script do cliente; python websocket_client.py
Troca de mensagens JSON via WebSocket
O JSON (JavaScript Object Notation) é um formato de intercâmbio de dados muito popular para a comunicação na Web. Para trocar dados JSON entre o servidor e o cliente, usamos a biblioteca json pré-instalada
No script do cliente, enviaremos um pedido em formato JSON. O servidor recebe este pedido, verifica os valores e envia uma resposta com o resultado da validação.
As funções que precisa de conhecer para gerir o formato JSON são:
- json.loads() para mudar de uma String para um dict
- json.dumps() para passar de um dict para uma String
Outros formatos Python podem ser convertidos no seu equivalente JSON
Python | JSON |
---|---|
dict | object |
list , tuple | array |
str | string |
int , float , int | number |
True | true |
False | false |
None | null |
guião do cliente
#!/usr/bin/env python # python3 -m pip install websockets import json import asyncio from websockets.sync.client import connect jsondata = {"type": "setParam", "param1": 30, "param2": 2.3} jsonwrong = {"type": "setParam", "param1": 30, "param2": -2.3} jsonunkn = {"type": "setData", "param1": 30, "param2": 2.3} def hello(): with connect("ws://192.168.1.52:8765") as websocket: websocket.send("Hello world!") message = websocket.recv() print(f"Received from server : {message}") websocket.send(json.dumps(jsondata)) message = websocket.recv() print(f"Received from server : {message}") websocket.send(json.dumps(jsonwrong)) message = websocket.recv() print(f"Received from server : {message}") websocket.send(json.dumps(jsonunkn)) message = websocket.recv() print(f"Received from server : {message}") hello()
script do servidor
#!/usr/bin/env python # python3 -m pip install websockets import json import asyncio from websockets.server import serve def getIpAddress(): import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ipaddress = s.getsockname()[0] s.close() return ipaddress ipaddress = getIpAddress() port = 8765 async def echo(websocket): async for message in websocket: print("received from {}:{} : ".format(websocket.remote_address[0],websocket.remote_address[1]) + message) if('{' not in message): await websocket.send(message) else: request = json.loads(message) answer = {} if(request['type'] == 'setParam'): answer['type'] = request['type'] if(request['param1']<100 and request['param2']>1.2): answer['valid'] = True for key, val in request.items(): print("\t"+key+": ", val) else: answer['valid'] = False else: answer['type'] = 'unknown' answer['valid'] = False await websocket.send(json.dumps(answer)) async def main(): print("Server is activated on ws://{}:{}".format(ipaddress,port)) #async with serve(echo, "localhost", 8765): async with serve(echo, "0.0.0.0", port): await asyncio.Future() # run forever asyncio.run(main())
Resultados