Ejecución en red con sockets

← Fundamentos de Python ⌂ Home

Objetivos

Desarrollo

Los sockets son los puntos finales de un canal de comunicación bidireccional utilizados por los programas para comunicarse con otros programas en la misma o diferente computadora, bajo la misma red.

Los sockets se pueden configurar para actuar como un servidor y escuchar los mensajes entrantes, o conectarse a otras aplicaciones como un cliente.

Módulo socket

Servidor

Comenzamos creando un objeto de tipo socket con host y puerto.

# ejemplo_1_servidor.py

import socket

servidor = socket.socket()
servidor.bind(('localhost', 9000))

El argumento del método bind es una tupla que contiene el host y el puerto. Necesitamos que nuestro servidor comience a aceptar conexiones entrantes, lo hacemos de la siguiente manera:

# ejemplo_1_servidor.py

import socket

servidor = socket.socket()
servidor.bind(('localhost', 9000))

print("Esperando conexiones...")
servidor.listen(1)

cliente, direccion = servidor.accept()
print('Conectado desde: ', direccion[0])

Con el método listen el socket se pone a la escucha de nuevas conexiones entrantes, accept se mantiene a la espera de conexiones entrantes, bloqueando la ejecución hasta que llegue un mensaje. Cuando llega un mensaje, accept desbloquea la ejecución, devolviendo un objeto socket que representa la conexión del cliente y una tupla que contiene el host y puerto de la conexión.

Listen requiere de un parámetro que indica el número de conexiones máximas que queremos aceptar.

Una vez realizada la conexión podemos comunicarnos con el cliente a través de los métodos recv y send, que permiten recibir o enviar mensajes respectivamente.

# ejemplo_1_servidor.py

import socket

servidor = socket.socket()
servidor.bind(('localhost', 9000))

print("Esperando conexiones...")
servidor.listen(1)

cliente, direccion = servidor.accept()
print('Conectado desde: ', direccion[0])

while True:
    mensaje = cliente.recv(1024).decode()
    if mensaje == "salir":
        break
    print(direccion[0] + " dice: " + mensaje)
    cliente.send("Mensaje recibido".encode())

servidor.close()
cliente.close()

Cliente

Realizar el socket cliente es muy similar, unicamente tenemos que indicar a donde queremos conectarnos (a nuestro socket servidor). Utilizar el método connect para conectarnos al servidor y utilizar los métodos send y recv que vimos anteriormente. El argumento de connect es una tupla con host y puerto (datos del servidor).

# ejemplo_1_cliente.py

import socket

cliente = socket.socket()
cliente.connect(("localhost", 9000))

while True:
    mensaje = input("Ingresa un mensaje: ")
    cliente.send(mensaje.encode())
    if mensaje == "salir":
        break
    respuesta = cliente.recv(1024).decode()
    print(respuesta)

cliente.close()

Envío de archivos

Para enviar un archivo por sockets se utiliza el método sendfile, como podemos ver en el siguiente ejemplo:

Servidor (recibirá el archivo)

# ejemplo_2_servidor.py

import socket

servidor = socket.socket()
servidor.bind(('localhost', 9000))

print("Esperando conexiones...")
servidor.listen(1)

cliente, direccion = servidor.accept()
print('Conectado desde: ', direccion[0])

archivo = cliente.recv(4096) # recibiendo el archivo
print("Archivo recibido con exito")

with open("archivo-copia.txt","wb") as archivo_copia:
    archivo_copia.write(archivo) # escribiendo el archivo

servidor.close()
cliente.close()

Cliente (enviará el archivo)

# ejemplo_2_cliente.py

import socket

cliente = socket.socket()
cliente.connect(("localhost", 9000))

archivo = input("Ingresa el archivo a enviar: ")

with open(archivo, "rb") as archivo_enviar:
    cliente.sendfile(archivo_enviar)

cliente.close()

Ejercicios

  1. Como ejercicio te recomiendo leer la siguiente publicación de un chat multihilo

Fuentes