PERSISTENCIA Y DATOS
SEMANA 3
PRESENTADO A:
RICARDO DAVID CAMARGO LEMOS
SUBGRUPO 7
ENTREGADO POR:
NESTOR STEVE CARRILLO GARCIA
CRISTIAN ESTEBAN CASTELLANOS CAMACHO
RAMOS RIOS JHOAN SNEYDER
INSTITUCIÓN UNIVERSITARIA POLITÉCNICO GRANCOLOMBIANO
BOGOTA, MAYO 2025
Contenido
Introducción...........................................................................................................................................................
Marco Teórico: Fundamentos de Programación con Sockets..........................................................................
Desarrollo de la actividad.....................................................................................................................................
Pruebas de funcionamiento...............................................................................................................................
Conclusiones...............................................................................................................................................................
Referencias.............................................................................................................................................................
Introducción
En la actualidad, las aplicaciones distribuidas y los sistemas en red son fundamentales
para la comunicación entre procesos y la compartición de recursos en entornos heterogéneos. El
uso de sockets como mecanismo de abstracción para el intercambio de datos entre programas
ofrece una solución flexible y estandarizada que se adapta a múltiples arquitecturas y protocolos
de transporte. Este proyecto se enfoca en el diseño e implementación de un sistema de chat
bidireccional simple, basado en sockets TCP/IP, donde un programa actúa como servidor y otro
como cliente. Antes de abordar el diseño y desarrollo, es imprescindible establecer un marco
teórico que describa los conceptos básicos de programación con sockets.
Marco Teórico: Fundamentos de Programación con Sockets
1. Concepto de Socket
Un socket es un punto final en una comunicación bidireccional entre dos procesos que
pueden residir en la misma máquina o en máquinas diferentes conectadas por una red.
Los sockets proporcionan una interfaz de programación de aplicaciones (API) para la
transmisión de datos mediante protocolos de transporte como TCP (orientado a conexión)
y UDP (sin conexión).
2. Modelo Cliente-Servidor
○ Servidor: Inicializa el socket, lo asocia a una dirección IP y puerto (bind),
escucha nuevas conexiones (listen) y acepta peticiones entrantes (accept).
○ Cliente: Crea un socket y solicita la conexión al servidor especificando su
dirección IP y puerto (connect).
○ Una vez establecida la conexión TCP, ambos extremos pueden enviar y recibir
datos de forma fiable y ordenada.
3. Principales Llamadas al Sistema
○ socket()
○ bind(address)
○ listen(backlog)
○ accept()
○ connect(address)
○ send(data) / sendall(data)
○ recv(bufsize)
○ close()
4. Dirección y Puerto
○ Dirección IP: Identificador numérico de 32 bits (IPv4) o 128 bits (IPv6).
○ Puerto: Número entero de 16 bits que identifica la aplicación dentro de un host.
Los puertos por debajo de 1024 están reservados para servicios estándar.
5. Manejo de Concurrencia
Para atender múltiples clientes, el servidor puede emplear:
○ Procesos: Crear un nuevo proceso por cada conexión (fork).
○ Hilos: Crear hilos livianos que compartan el espacio de memoria del servidor
principal.
○ E/S no bloqueante y multiplexación: Usar select(), poll() o mecanismos basados
en eventos (por ejemplo, epoll en Linux).
6. Aspectos de Fiabilidad y Control de Errores
○ En TCP, la fiabilidad, control de flujo y corrección de errores están garantizados
por el protocolo.
○ El programador debe gestionar excepciones por caídas de conexión, timeouts y
cierres inesperados.
7. Protocolos de Aplicación
Si bien TCP garantiza la entrega de octetos, es responsabilidad del desarrollador definir
el formato de los mensajes (p. ej., longitud fija, delimitadores, encabezados) para que el
receptor pueda interpretar correctamente el flujo de datos.
Desarrollo de la actividad
Socket Servidor
import socket
import threading
# Configuración del servidor\
HOST = 'localhost' # IP del servidor (localhost)
PORT = 5000 # Puerto de escucha
# Estructura para almacenar clientes conectados: {username: conn}
clients = {}
clients_lock = [Link]()
# Función para enviar el listado de usuarios conectados a un cliente
def send_user_list(conn):
with clients_lock:
users = list([Link]())
data = "|".join(users)
[Link]([Link]())
# Hilo que gestiona cada cliente
def handle_client(conn, addr):
try:
# 1. Recibir nombre de usuario
username = [Link](1024).decode().strip()
if not username:
[Link]()
return
# Registrar cliente
with clients_lock:
clients[username] = conn
print(f"[+] Usuario conectado: {username} desde {addr}")
# 2. Enviar log de usuarios al cliente
send_user_list(conn)
# 3. Esperar nombre del usuario destino para iniciar chat
target = [Link](1024).decode().strip()
if target not in clients:
[Link](f"Error: usuario {target} no
disponible".encode())
[Link]()
with clients_lock:
del clients[username]
return
[Link](f"Conectado con {target}".encode())
# 4. Reenviar mensajes entre cliente y destino
target_conn = clients[target]
print(f"[+] Iniciando chat entre {username} y {target}")
while True:
msg = [Link](1024)
if not msg:
break
text = [Link]().strip()
if [Link]() == 'chao':
break
forward = f"{username}: {text}".encode()
target_conn.sendall(forward)
# Cierre de chat
[Link](b"--- Chat terminado ---")
print(f"[-] Usuario desconectado: {username}")
except Exception as e:
print(f"[!] Error con {addr}: {e}")
finally:
# Limpiar registro
with clients_lock:
if username in clients:
del clients[username]
[Link]()
# Función principal para iniciar el servidor
def main():
server_sock = [Link](socket.AF_INET, socket.SOCK_STREAM)
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_sock.bind((HOST, PORT))
server_sock.listen(5)
print(f"Servidor escuchando en {HOST}:{PORT}...")
try:
while True:
conn, addr = server_sock.accept()
thread = [Link](target=handle_client, args=(conn,
addr), daemon=True)
[Link]()
except KeyboardInterrupt:
print("\nServidor detenido manualmente.")
finally:
server_sock.close()
if __name__ == '__main__':
main()
Socket Cliente
import socket
import threading
# Función para recibir mensajes del servidor
def receive_messages(sock):
try:
while True:
data = [Link](1024)
if not data:
break
print([Link]())
except Exception as e:
print(f"[!] Error recibiendo datos: {e}")
# Función principal
def main():
# Datos de conexión provistos por el usuario
host = input("Ingrese la IP del servidor (por defecto [Link]): ")
or '[Link]'
port_str = input("Ingrese el puerto del servidor (por defecto 5000):
") or '5000'
try:
port = int(port_str)
except ValueError:
print("Puerto inválido, usando 5000.")
port = 5000
username = input("Ingrese su nombre de usuario: ").strip()
if not username:
print("El nombre de usuario no puede estar vacío.")
return
# Conexión al servidor
sock = [Link](socket.AF_INET, socket.SOCK_STREAM)
try:
[Link]((host, port))
except Exception as e:
print(f"[!] No se pudo conectar al servidor: {e}")
return
# Enviar nombre de usuario
[Link]([Link]())
# Recibir lista de usuarios conectados
data = [Link](2048).decode().strip()
users = [Link]('|') if data else []
print("Usuarios conectados:")
for u in users:
print(f" - {u}")
# Seleccionar usuario destino
target = input("Seleccione el usuario con quien chatear: ").strip()
[Link]([Link]())
# Mostrar respuesta del servidor
response = [Link](1024).decode()
print(response)
if [Link]("Error"):
[Link]()
return
# Iniciar hilo para recibir mensajes
recv_thread = [Link](target=receive_messages,
args=(sock,), daemon=True)
recv_thread.start()
# Enviar mensajes
try:
while True:
msg = input()
if not msg:
continue
[Link]([Link]())
if [Link]() == 'chao':
break
except KeyboardInterrupt:
[Link](b'chao')
finally:
[Link]()
print("Conexión finalizada.")
if __name__ == '__main__':
main()
Pruebas de funcionamiento
Figura 1: Comunicación entre Luna y Henry a través de un servidor y comunicación por
sockets
Conclusiones
Envío el link del video con el ejercicio propuesto:
[Link]
La programación con sockets ofrece un mecanismo poderoso y portátil para construir
sistemas distribuidos y aplicaciones de red, lo cual es importante en el mundo moderno
hiperconectado.
Comprender la API de sockets y el modelo cliente-servidor es clave para diseñar
protocolos de comunicación eficientes y fiables.
El manejo de la concurrencia y la gestión de errores son aspectos críticos que determinan
la escalabilidad y robustez de la aplicación de red.
Un correcto diseño de protocolo de aplicación (formato de mensajes, delimitadores,
control de sesión) facilita el desarrollo y mantenimiento, reduciendo la complejidad en la capa de
transporte.
Referencias
Forouzan, B. A. (2007). TCP/IP Protocol Suite (3.ª ed.). McGraw-Hill.
Stevens, W. R., Fenner, B., & Rudoff, A. M. (2004). Unix Network Programming,
Volume 1: The Sockets Networking API (3.ª ed.). Pearson.
Comer, D. E. (2006). Internetworking with TCP/IP, Volume 1: Principles, Protocols, and
Architecture (5.ª ed.). Prentice Hall.
Postel, J. (1981). Transmission Control Protocol. RFC 793. Recuperado de
[Link]
Python Software Foundation. (2025). socket — Low-level networking interface. En
Python 3.11.5 documentation. [Link]