Proyecto1AVApsp/servidor.py

85 lines
2.4 KiB
Python

#!/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()