#!/usr/bin/env python3 """ Servidor de mensajería simple (broadcast) - puerto 3333 Ejecutar en un terminal separado: python3 servidor.py """ import socket import threading HOST = '0.0.0.0' PORT = 3333 clients = [] clients_lock = threading.Lock() def broadcast(message: bytes, sender: socket.socket): with clients_lock: for client in list(clients): if client is sender: continue try: client.sendall(message) except Exception: try: client.close() except Exception: pass clients.remove(client) def handle_client(client_socket: socket.socket, client_address): print(f"[NUEVO CLIENTE] {client_address} conectado.") try: while True: data = client_socket.recv(4096) if not data: break text = data.decode('utf-8', errors='replace') print(f"[{client_address}] {text}") # Re-enviar a los demás broadcast(data, client_socket) except Exception as e: print(f"[ERROR] {client_address}:", e) finally: with clients_lock: if client_socket in clients: clients.remove(client_socket) try: client_socket.close() except Exception: pass print(f"[DESCONECTADO] {client_address} cerrado.") def start_server(): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((HOST, PORT)) server.listen(10) print(f"[INICIO] Servidor escuchando en {HOST}:{PORT}") try: while True: client_socket, client_address = server.accept() with clients_lock: clients.append(client_socket) t = threading.Thread(target=handle_client, args=(client_socket, client_address), daemon=True) t.start() except KeyboardInterrupt: print('\n[APAGANDO] Servidor detenido por el usuario') finally: with clients_lock: for c in clients: try: c.close() except Exception: pass try: server.close() except Exception: pass if __name__ == '__main__': start_server()