martes, 17 de septiembre de 2024

Python Sockets, manipular datos recibidos por cliente

Ahora que ya tengo en marchar Terminal DCC, una de las cosas que más me ha llamado la atención es la plasticidad de la biblioteca "sockets".

¿Que son los sockets?

De una manera simple, son los puntos de conexión entre procesos de diferentes sistemas a través de una red.

Con sockets no solo podemos transmitir texto entre cliente y servidor, también números, tanto int como float, binarios como imágenes o vídeo en resumen podemos enviar cualquier información que pueda ser representada como una secuencia de bytes.

Los usos más comunes que se le da a los sockets son como:

  • Servidor web
  • Transferencia de archivos
  • Clientes de chat
  • Juegos en red

En este ejemplo recibiremos los datos desde un servidor en formato bytes y los pasaremos a una codificación "UTF-8" para poder manejarlo como un String desde la misma u otra clase diferente.

Conceptos básicos:

  • Socket: Es el punto de conexión entre dos procesos. Se caracteriza por una dirección (IP) y un puerto.
  • Dirección IP: Es una etiqueta numérica única que identifica un dispositivo en una red.
  • Puerto: Es un número que identifica un servicio específico en un dispositivo.
  • TCP/IP: Es el protocolo de comunicación más utilizado en Internet. TCP (Transmission Control Protocol) garantiza la entrega ordenada y fiable de datos, mientras que IP (Internet Protocol) se encarga del enrutamiento de paquetes de datos. 
  •  

Consideraciones importantes:

  • Serialización: Para enviar objetos de Python, debes serializarlos en una secuencia de bytes. Pickle es un módulo estándar de Python que permite la serialización de objetos, pero ten en cuenta que los objetos serializados con pickle pueden no ser compatibles entre diferentes versiones de Python.
  • Protocolo: El protocolo de comunicación que utilices (TCP, UDP, etc.) influirá en la forma en que se envían y reciben los datos.
  • Codificación: Es crucial elegir la codificación correcta para los datos de texto. La codificación UTF-8 es muy común, pero existen otras opciones.

Empecemos con el servidor:

Tanto el servidor como el cliente son clases. Para llamar a la clase "serverSocket" tenemos que pasarle los parámetros "IP" y "puerto"


## Inicia el programa principal
if __name__ == '__main__':
	# Inicia el socket con los parametros IP y puerto
	# Si no especificamos una dirección IP y usamos un 
	# String vacío, socket usará la IP de la maquina.
	server = serverSocket("", 1314)

	# Inicia el servidor
	server.iniciar()
    

Al iniciar el servidor con "python3 class_server_test.py", aparecerá el siguiente mensaje


[START] Server starting at 192.168.0.25
[LISTENING] Waiting for connections... 

Con esto ya tenemos el servidor a la escucha esperando conexiones desde los clientes

Cliente conectando con el servidor:

Del otro lado tenemos al cliente al que llamaremos "clienteSocket" desde el archivo "class_cliente_test.py" y al que tenemos que pasar los parámetros que usará para establecer la conexión con el servidor y son la IP del servidor, el puerto que esta a la escucha en el servidor y el número de cliente en caso de que conectemos mas de un cliente.


## Inicia el programa cliente
if __name__ == '__main__':
	# Establece conexión con el servidor
	cliente = clienteSocket("192.168.0.25", 1314, 1)

	# Inicia la conexión con el servidor
	estado = cliente.iniciar()
	
	# Imprime en pantalla el estado del servidor
	print(estado)

	# Si el estado contiene la palabra "CONNECTED"
	if "CONNECTED" in estado:

		# Envía un mensaje al servidor comunicando que estamos conectados
		cliente.clientSendData("Cliente conectado...")
		
		# Inicia un bucle con la respuesta del resta del servidor
		while True:

			# imprime los datos desde el cliente
			print(cliente.get_client_data())

			cliente.clientSendData(cliente.get_client_data())
			
			# Espera 2 segundos para volver a leer los datos
			time.sleep(2)

Si todo esta correcto en la pantalla del cliente se imprime el mensaje:


	[CONNECTED] 192.168.0.25:1314
    
	[OK] datos recibidos
    

Ahora ya tenemos el sistema conectado. Pero nosotros los datos que necesitamos no se van a quedar en el la clase cliente, queremos mostrarlos en otra pantalla como una interfaz con Tkinter o pyTermTk.

Los datos los obtenemos desde la función "cliente.get_client_data()" Es necesario tenerlo en bucle "while" o un "hilo" para que este constantemente a la escucha de los nuevos datos


## Iniciar el cliente desde otra clase:
cliente = clienteSocket("192.168.0.25", 1314, 1)
cliente.iniciar()

# Obtener datos del cliente desde otra clase:
datas = cliente.get_client_data()

Y de está manera tenemos los datos de una conexión socket disponible para conectar cualquier dispositivo a nuestra red. 

 

Conexión Cliente - Servidor


Con algunas modificaciones, estos ejemplos pueden servir para conectar dispositivos tan dispares como:

  • Ordenadores: Sobremesa, portátil, servidor...
  • Raspberry Pi: En todas sus versiones
  • Microcontroladores: Dispositivos como ESP8266 o ESP32

Programa de ejemplo de este articulo en GitHub

Espero que este ejemplo sea de ayuda y mejore las conexiones entre vuestros dispositivos, tanto tradicionales como IoT.

 Saludos!!

No hay comentarios :

Publicar un comentario