Site icon AranaCorp

Comunicação entre servidor e cliente WebSockets com Python

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:

Outros formatos Python podem ser convertidos no seu equivalente JSON

PythonJSON
dictobject
list, tuplearray
strstring
int, float, intnumber
Truetrue
Falsefalse
Nonenull

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

Fontes

Exit mobile version