diff --git a/main.py b/main.py new file mode 100644 index 0000000..e08524a --- /dev/null +++ b/main.py @@ -0,0 +1,101 @@ +import socket +import threading +import tkinter as tk +from tkinter import scrolledtext +from server import start_server # Importamos la función para iniciar el servidor + +# Configuración del cliente +SERVER_HOST = '127.0.0.1' +SERVER_PORT = 3333 + +class ChatApp: + def __init__(self, root): + self.root = root + self.root.title("Chat Cliente-Servidor") + + # Botón para iniciar el servidor + self.server_button = tk.Button(root, text="Iniciar Servidor", command=self.start_server) + self.server_button.grid(row=0, column=0, padx=10, pady=10) + + # Botón para conectar el cliente + self.connect_button = tk.Button(root, text="Conectar Cliente", command=self.start_client) + self.connect_button.grid(row=0, column=1, padx=10, pady=10) + + # Área de chat + self.chat_display = scrolledtext.ScrolledText(root, wrap=tk.WORD, state='disabled', width=50, height=20) + self.chat_display.grid(row=1, column=0, padx=10, pady=10, columnspan=2) + + # Campo de entrada de mensajes + self.message_entry = tk.Entry(root, width=40) + self.message_entry.grid(row=2, column=0, padx=10, pady=10) + + # Botón para enviar mensajes + self.send_button = tk.Button(root, text="Enviar", command=self.send_message, state='disabled') + self.send_button.grid(row=2, column=1, padx=10, pady=10) + + self.client_socket = None # Se inicializa el socket del cliente en None + self.connected = False # Variable para manejar el estado de conexión + + def start_server(self): + """ Inicia el servidor en segundo plano """ + threading.Thread(target=start_server, daemon=True).start() + self.append_message("[SERVIDOR] Servidor iniciado en segundo plano...\n") + + def start_client(self): + """ Conecta el cliente al servidor """ + if self.connected: + self.append_message("[CLIENTE] Ya estás conectado al servidor.\n") + return + + # Intentar crear un nuevo socket + self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + self.client_socket.connect((SERVER_HOST, SERVER_PORT)) + self.append_message(f"[CONECTADO] Conectado al servidor {SERVER_HOST}:{SERVER_PORT}\n") + threading.Thread(target=self.receive_messages, daemon=True).start() + self.send_button.config(state='normal') # Habilitar botón de enviar mensajes + self.connected = True + except ConnectionRefusedError: + self.append_message("[ERROR] El servidor no está disponible. Inícialo primero.\n") + self.client_socket = None # Restablecer socket para permitir nuevos intentos + except Exception as e: + self.append_message(f"[ERROR] No se pudo conectar al servidor: {e}\n") + self.client_socket = None # Restablecer socket + + def receive_messages(self): + """ Recibe mensajes del servidor en un hilo separado """ + while True: + try: + message = self.client_socket.recv(1024) + if not message: + break + self.append_message(message.decode('utf-8')) + except: + self.append_message("[ERROR] Conexión perdida con el servidor.\n") + self.client_socket.close() + self.client_socket = None + self.connected = False + self.send_button.config(state='disabled') # Deshabilitar el botón de enviar + break + + def send_message(self): + """ Envía un mensaje al servidor """ + message = self.message_entry.get() + if message and self.client_socket: + try: + self.client_socket.send(message.encode('utf-8')) + self.message_entry.delete(0, tk.END) + except: + self.append_message("[ERROR] No se pudo enviar el mensaje.\n") + + def append_message(self, message): + """ Agrega un mensaje a la ventana de chat """ + self.chat_display.config(state='normal') + self.chat_display.insert(tk.END, message + '\n') + self.chat_display.config(state='disabled') + self.chat_display.yview(tk.END) + +if __name__ == "__main__": + root = tk.Tk() + app = ChatApp(root) + root.mainloop() diff --git a/server.py b/server.py new file mode 100644 index 0000000..834b61e --- /dev/null +++ b/server.py @@ -0,0 +1,43 @@ +import socket +import threading + +# Configuración del servidor +HOST = '0.0.0.0' +PORT = 3333 +clients = [] + +def broadcast(message, client_socket): + for client in clients: + if client != client_socket: + try: + client.send(message) + except: + clients.remove(client) + +def handle_client(client_socket, client_address): + print(f"[NUEVO CLIENTE] {client_address} conectado.") + while True: + try: + message = client_socket.recv(1024) + if not message: + break + print(f"[{client_address}] {message.decode('utf-8')}") + broadcast(message, client_socket) + except: + print(f"[DESCONECTADO] {client_address} se ha desconectado.") + clients.remove(client_socket) + client_socket.close() + break + +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(5) + print(f"[INICIO] Servidor escuchando en {HOST}:{PORT}") + + while True: + client_socket, client_address = server.accept() + clients.append(client_socket) + print(f"[CONECTADO] Nueva conexión desde {client_address}") + threading.Thread(target=handle_client, args=(client_socket, client_address)).start()